Merge branch 'master' into describable

This commit is contained in:
Tim Jacomb authored and GitHub committed 2025-04-02 22:17:10 +01:00
commit 226efff8fa
72 files changed
+337 -760

No files matched your search

+1 -1
View File
@@ -6,7 +6,7 @@ set -o xtrace
cd "$(dirname "$0")"
# https://github.com/jenkinsci/acceptance-test-harness/releases
export ATH_VERSION=6133.v358d9a_47674f
export ATH_VERSION=6169.v8b_0662286b_b_7
if [[ $# -eq 0 ]]; then
export JDK=17
+2 -2
View File
@@ -89,7 +89,7 @@ THE SOFTWARE.
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.4.5-jre</version>
<version>33.4.6-jre</version>
</dependency>
<dependency>
<groupId>com.sun.xml.txw2</groupId>
@@ -331,7 +331,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.7.1</version>
<version>9.8</version>
</dependency>
<dependency>
<!-- provided by jcl-over-slf4j -->
@@ -61,6 +61,7 @@ import jenkins.model.IComputer;
import jenkins.model.Jenkins;
import jenkins.model.ModelObjectWithChildren;
import jenkins.model.ModelObjectWithContextMenu.ContextMenu;
import jenkins.security.ExtendedReadRedaction;
import jenkins.util.Timer;
import jenkins.widgets.HasWidgets;
import net.sf.json.JSONObject;
@@ -75,6 +76,7 @@ import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import org.kohsuke.stapler.interceptor.RequirePOST;
import org.kohsuke.stapler.verb.POST;
import org.springframework.security.access.AccessDeniedException;
/**
* Serves as the top of {@link Computer}s in the URL hierarchy.
@@ -291,8 +293,23 @@ public final class ComputerSet extends AbstractModelObject implements Describabl
}
}
src.checkPermission(Computer.EXTENDED_READ);
// copy through XStream
String xml = Jenkins.XSTREAM.toXML(src);
if (!src.hasPermission(Computer.CONFIGURE)) {
final String redactedConfigDotXml = ExtendedReadRedaction.applyAll(xml);
if (!xml.equals(redactedConfigDotXml)) {
// AccessDeniedException2 does not permit a custom message, and anyway redirecting the user to the login screen is obviously pointless.
throw new AccessDeniedException(
Messages.ComputerSet_may_not_copy_as_it_contains_secrets_and_(
src.getNodeName(),
Jenkins.getAuthentication2().getName(),
Computer.PERMISSIONS.title,
Computer.EXTENDED_READ.name,
Computer.CONFIGURE.name));
}
}
Node result = (Node) Jenkins.XSTREAM.fromXML(xml);
result.setNodeName(name);
result.holdOffLaunchUntilSave = true;
@@ -40,7 +40,6 @@ import org.kohsuke.stapler.DataBoundConstructor;
/**
* Checks available disk space of the remote FS root.
* Requires Mustang.
*
* @author Kohsuke Kawaguchi
* @since 1.123
@@ -35,7 +35,7 @@ import org.springframework.security.core.Authentication;
* Holds information of a command execution. Same instance is used to all {@link CLIListener} invocations.
* Use {@code correlationId} in order to group related events to the same command.
*
* @since TODO
* @since 2.503
*/
public class CLIContext {
private final String correlationId = UUID.randomUUID().toString();
@@ -31,7 +31,7 @@ import hudson.cli.CLICommand;
/**
* Allows implementations to listen to {@link CLICommand#run()} execution events.
*
* @since TODO
* @since 2.503
*/
public interface CLIListener extends ExtensionPoint {
@@ -26,9 +26,10 @@ import jenkins.util.SystemProperties;
* Default portable implementation of {@link ConfidentialStore} that uses
* a directory inside $JENKINS_HOME.
* <p>
* The master key is stored by default in <code>$JENKINS_HOME/secrets/master.key</code> but another location can be provided using the system property <code>jenkins.master.key.file</code>.
* The master key is stored by default in <code>$JENKINS_HOME/secrets/master.key</code> but another location can be provided using the system property <code>jenkins.security.DefaultConfidentialStore.file</code>.
* <p>
* It is also possible to prevent the generation of the master key file using the system property <code>-Djenkins.master.key.readOnly</code>. In this case, the master key file must be provided or startup will fail.
* It is also possible to prevent the generation of the master key file using the system property <code>jenkins.security.DefaultConfidentialStore.readOnly</code>.
* In this case, the master key file must be provided or startup will fail.
*
* @author Kohsuke Kawaguchi
*/
@@ -108,8 +108,8 @@ public abstract class WebSocketSession {
return handler.sendBinary(data);
}
protected final void sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException {
handler.sendBinary(partialByte, isLast);
protected final Future<Void> sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException {
return handler.sendBinary(partialByte, isLast);
}
protected final Future<Void> sendText(String text) throws IOException {
@@ -24,8 +24,7 @@ THE SOFTWARE.
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<l:layout title="${%Manage Old Data}">
<st:include page="sidepanel.jelly" it="${app}"/>
<l:layout title="${%Manage Old Data}" type="one-column">
<!-- no need for additional breadcrumb here as we're on an "index" page already including breadcrumb -->
<l:main-panel>
<h1>${%Manage Old Data}</h1>
@@ -27,8 +27,7 @@ THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
<l:layout title="${%Nodes}">
<st:include page="sidepanel.jelly" />
<l:layout title="${%Nodes}" type="one-column">
<!-- no need for additional breadcrumb here as we're on an index page already including breadcrumb -->
<l:main-panel>
<l:app-bar title="${%Nodes}">
@@ -1,42 +0,0 @@
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:cactusman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<!--
Side panel
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
<l:header />
<l:side-panel>
<l:tasks>
<l:task href="${h.getNearestAncestorUrl(request2,it)}/" icon="symbol-computer"
title="${%Nodes}"/>
<l:task href="../cloud/" icon="symbol-cloud" permission="${app.SYSTEM_READ}"
title="${app.hasPermission(app.ADMINISTER) ? '%Clouds' : '%View Clouds'}"/>
</l:tasks>
<j:forEach var="w" items="${it.widgets}">
<st:include it="${w}" page="index" />
</j:forEach>
</l:side-panel>
</j:jelly>
@@ -1,30 +0,0 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2015, 2016, Alexander Shopov <ash@kambanaria.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=\
Към основния екран
Configure=\
Настройки
Manage\ Jenkins=\
Управление на Jenkins
New\ Node=\
Нова машина
@@ -1,6 +0,0 @@
# This file is under the MIT License by authors
Back\ to\ Dashboard=Tornar al tauler
Configure=Configurar
Manage\ Jenkins=Gestionar Jenkins
New\ Node=Nou node
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Zpět na hlavní stránku
Configure=Nastavení
Manage\ Jenkins=Spravovat Jenkins
New\ Node=Nový uzel
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc. Kohsuke Kawaguchi. Knud Poulsen.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Configure=Konfigurer
Back\ to\ Dashboard=Tilbage til oversigtssiden
Manage\ Jenkins=Bestyr Jenkins
New\ Node=Ny Node
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Simon Wiest
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Zurück zur Übersicht
New\ Node=Neuer Knoten
Configure=Konfigurieren
Manage\ Jenkins=Jenkins verwalten
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Επιστροφή στο Dashboard
Manage\ Jenkins=Διαχείριση Jenkins
Configure=Παραμετροποίηση
New\ Node=Νέος Κόμβος
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Volver al Panel de control
Manage\ Jenkins=Administrar Jenkins
New\ Node=Nuevo nodo
Configure=Configuración
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Takaisin kojetauluun
Configure=Konfiguroi
Manage\ Jenkins=Hallinnoi Jenkinsiä
New\ Node=Uusi noodi
@@ -1,27 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Eric Lefevre-Ardant
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Retour au tableau de bord
Manage\ Jenkins=Administrer Jenkins
Configure=Configurer
New\ Node=Créer un nœud
@@ -1,5 +0,0 @@
# This file is under the MIT License by authors
Back\ to\ Dashboard=חזרה למסך הראשי
Configure=הגדר
Manage\ Jenkins=נהל את ג''נקינס
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Vissza a Irányítópultra
Configure=Megjelenítés beállítása
Manage\ Jenkins=Jenkins Kezelés
New\ Node=Új Csomópont
@@ -1,29 +0,0 @@
# The MIT License
#
# Italian localization plugin for Jenkins
# Copyright © 2020 Alessandro Menti
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Torna al cruscotto
Configure\ Clouds=Configura cloud
Manage\ Jenkins=Gestisci Jenkins
New\ Node=Nuovo nodo
Node\ Monitoring=Monitoraggio nodo
View\ Clouds=Visualizza cloud
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe, id:cactusman
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=ダッシュボードへ戻る
Manage\ Jenkins=Jenkinsの管理
New\ Node=新規ノード作成
Configure=設定
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=대시보드로 돌아가기
Manage\ Jenkins=Jenkins 관리
Configure=설정
New\ Node=신규 노드
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Atgal į darbalaukį
Configure=Nustatymai
Manage\ Jenkins=Valdyti Jenkins
New\ Node=Naujas mazgas
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Atpakaļ uz Uzdevumdēli
Configure=Konfigurēt
Manage\ Jenkins=Pārvaldīt Jenkins
New\ Node=Jauna Node
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=tilbake til kontrollpanelet
Configure=Konfigurer
Manage\ Jenkins=Sett opp Jenkins
New\ Node=Ny node
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:sorokh
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Terug naar dashboard
Manage\ Jenkins=Jenkins Beheren
Configure=Configureren
New\ Node=Nieuwe node
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Powrót do tablicy
Configure=Konfiguruj
Manage\ Jenkins=Zarządzaj Jenkinsem
New\ Node=Nowy węzeł
@@ -1,25 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number
# of other of contributors.
# Copyright (c) 2022- Jenkins contributors.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Configure\ Clouds=Configurar\ nuvens
Node\ Monitoring=Monitoração\ de\ nó
@@ -1,6 +0,0 @@
# This file is under the MIT License by authors
Back\ to\ Dashboard=Voltar ao Quadro Geral
Configure=Configurar
Manage\ Jenkins=Gerir o Jenkins
New\ Node=Novo Nó
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Mike Salnikov
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Домой
Manage\ Jenkins=Настроить Jenkins
Configure=Настройки
New\ Node=Новый узел
@@ -1,6 +0,0 @@
# This file is under the MIT License by authors
Back\ to\ Dashboard=Naspäť na Dashboard
Configure=Konfiguruj
Manage\ Jenkins=Spravuj Jenkins
New\ Node=Nový stroj
@@ -1,3 +0,0 @@
# This file is under the MIT License by authors
Back\ to\ Dashboard=Nazaj na pregled
@@ -1,6 +0,0 @@
# This file is under the MIT License by authors
Manage\ Jenkins=Управљање Jenkins-ом
New\ Node=Нова машина
Configure=Подеси
Back\ to\ Dashboard=Назад ка контролну панелу
@@ -1,10 +0,0 @@
# This file is under the MIT License by authors
Back\ to\ Dashboard=Tillbaka till instrumentpanelen
Configure=Konfigurera
New\ Node=Ny nod
Node\ Monitoring=Nodövervakning
Manage\ Jenkins=Hantera Jenkins
Nodes=Noder
Clouds=Moln
View\ Clouds=Visa moln
@@ -1,26 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Oguz Dag
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=Kontrol Merkezi'ne Dön
Manage\ Jenkins=Jenkins''i Yönet
Nodes=Sunucular
Clouds=Bulutlar
@@ -1,6 +0,0 @@
# This file is under the MIT License by authors
Back\ to\ Dashboard=Повернутись до Панелі Управління
Configure=Налаштувати
Manage\ Jenkins=Налаштувати Jenkins
New\ Node=Додати вузол
@@ -1,29 +0,0 @@
# The MIT License
#
# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co.,
# and Ltd., Pei-Tang Huang
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=返回資訊主頁
Manage\ Jenkins=管理 Jenkins
New\ Node=新增節點
Configure=設定
Configure\ Clouds=設定雲端
Node\ Monitoring=節點監視
@@ -112,6 +112,7 @@ ComputerSet.NoSuchSlave=No such agent: {0}
ComputerSet.SlaveAlreadyExists=Agent called ‘{0}’ already exists
ComputerSet.SpecifySlaveToCopy=Specify which agent to copy
ComputerSet.DisplayName=Nodes
ComputerSet.may_not_copy_as_it_contains_secrets_and_=May not copy {0} as it contains secrets and {1} has {2}/{3} but not /{4}
Descriptor.From=(from <a href="{1}" rel="noopener noreferrer" target="_blank">{0}</a>)
@@ -155,6 +155,11 @@ CLI.wait-node-offline.shortDescription=\
ComputerSet.DisplayName=\
Компютри
# May not copy {0} as it contains secrets and {1} has {2}/{3} but not /{4}
ComputerSet.may_not_copy_as_it_contains_secrets_and_=\
Не може да копирате „{0}“, защото на него има пароли, а „{1}“ има {2}/{3}, но\
не и /{4}
Descriptor.From=\
(от <a href="{1}">{0}</a>)
@@ -107,6 +107,7 @@ ComputerSet.DisplayName=Knoten
ComputerSet.NoSuchSlave=Agent existiert nicht: „{0}“
ComputerSet.SlaveAlreadyExists=Ein Agent mit dem Namen „{0}“ existiert bereits.
ComputerSet.SpecifySlaveToCopy=Geben Sie an, welcher Agent kopiert werden soll
ComputerSet.may_not_copy_as_it_contains_secrets_and_=Kann „{0}“ nicht kopieren, da es Geheimnisse enthält und „{1}“ nur {2}/{3} aber nicht /{4} hat.
Descriptor.From=(aus <a href="{1}">{0}</a>)
@@ -107,6 +107,7 @@ ComputerSet.NoSuchSlave=Aucun agent: {0}
ComputerSet.SlaveAlreadyExists=L''agent ‘{0}’ existe déjà
ComputerSet.SpecifySlaveToCopy=Quel agent à copier
ComputerSet.DisplayName=Nœuds
ComputerSet.may_not_copy_as_it_contains_secrets_and_=Copie impossible de {0} car il contient des secrets et {1} possède {2}/{3} mais pas /{4}
Descriptor.From=(de <a href="{1}" rel="noopener noreferrer" target="_blank">{0}</a>)
@@ -156,6 +156,8 @@ ComputerSet.DisplayName=Nodi
ComputerSet.NoSuchSlave=L''agente {0} non esiste
ComputerSet.SlaveAlreadyExists=Un agente di nome "{0}" esiste già
ComputerSet.SpecifySlaveToCopy=Specificare l''agente da copiare
ComputerSet.may_not_copy_as_it_contains_secrets_and_=Impossibile copiare \
{0} perché contiene segreti e {1} ha {2}/{3} ma non /{4}
Descriptor.From=(da <a href="{1}">{0}</a>)
Executor.NotAvailable=N/D
FileParameterDefinition.DisplayName=Parametro file
@@ -105,6 +105,8 @@ UpdateCenter.Status.Success=Sucesso
UpdateCenter.init=Iniciando o centro de atualização
ParameterAction.DisplayName=Parâmetros
ComputerSet.DisplayName=Nós
ComputerSet.may_not_copy_as_it_contains_secrets_and_=Pode não conseguir copiar {0} já que contem segredos e {1} \
tem {2}/{3} mas não /{4}
Run.DeletePermission.Description=\
Esta permissão concede aos usuários o direito de manualmente apagarem construções do histórico de construções.
Run.Summary.BrokenForALongTime=Quebrado há muito tempo
@@ -85,6 +85,7 @@ Computer.BadChannel=Машина агента није повезана или
ComputerSet.SlaveAlreadyExists=Већ постоји агент са именом {0}
ComputerSet.SpecifySlaveToCopy=Одредите агент за копирање
ComputerSet.DisplayName=Рачунари
ComputerSet.may_not_copy_as_it_contains_secrets_and_=Неможе се копирати {0} пошто садржи тајне и {1} има {2}/{3} а не /{4}
Descriptor.From=(од <a href="{1}">{0}</a>)
Executor.NotAvailable=Н/Д
FreeStyleProject.DisplayName=Независни задатак
@@ -112,6 +112,7 @@ ComputerSet.NoSuchSlave=Det finns ingen sådan agent: {0}
ComputerSet.SlaveAlreadyExists=En agent med namnet "{0}" finns redan
ComputerSet.SpecifySlaveToCopy=Ange vilken agent som ska kopieras
ComputerSet.DisplayName=Noder
ComputerSet.may_not_copy_as_it_contains_secrets_and_=Kan inte kopiera {0} eftersom den innehåller hemligheter och {1} har {2}/{3} men inte /{4}
Descriptor.From=(från <a href="{1}" rel="noopener noreferrer" target="_blank">{0}</a>)
@@ -6,7 +6,7 @@ def f = namespace(lib.FormTagLib)
def l = namespace(lib.LayoutTagLib)
def st = namespace("jelly:stapler")
l.layout(norefresh: true, permission: app.MANAGE, title: my.displayName) {
l.layout(permission: app.MANAGE, title: my.displayName, type: "one-column") {
l.main_panel {
h1 {
text(Messages.ShutdownLink_DisplayName_prepare())
@@ -24,8 +24,7 @@ THE SOFTWARE.
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<l:layout title="${it.displayName} ${%Load Statistics}">
<st:include page="sidepanel.jelly" />
<l:layout title="${it.displayName} ${%Load Statistics}" type="one-column">
<l:breadcrumb title="${%Load Statistics}"/>
<l:main-panel>
<j:set var="prefix" value="overallLoad" />
@@ -27,12 +27,12 @@ THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<l:layout permissions="${app.MANAGE_AND_SYSTEM_READ}" title="${%System Information}">
<l:layout permissions="${app.MANAGE_AND_SYSTEM_READ}" title="${%System Information}" type="one-column">
<l:header>
<script src="${resURL}/jsbundles/section-to-tabs.js" type="text/javascript" defer="true" />
<script src="${resURL}/jsbundles/pages/manage-jenkins/system-information.js" type="text/javascript" defer="true" />
</l:header>
<st:include page="sidepanel.jelly" />
<l:breadcrumb title="${%System Information}"/>
<l:main-panel>
<l:app-bar title="${%System Information}" />
@@ -27,21 +27,19 @@
}
.hidden-password-legend {
border: 1px solid #ccc;
border: 1px solid var(--input-border);
border-radius: 3px;
background: #f9f9f9;
background: var(--input-hidden-password-bg-color);
border: var(--jenkins-border-width) solid var(--input-border);
border-radius: var(--form-input-border-radius);
background: var(--input-color);
flex-grow: 1;
align-items: center;
display: inline-flex;
}
.hidden-password-legend > svg {
margin-right: 1em;
margin-left: 0.5em;
margin-right: 0.75em;
margin-left: 0.75em;
}
.hidden-password-update-btn {
margin-left: 5px;
margin-left: calc(var(--section-padding) / 2);
}
@@ -100,8 +100,8 @@ Example usage:
</div>
</div>
<div class="secret-input">
<textarea id="${id}" hidden="hidden" name="${name}" placeholder="${placeholder}"
class="secretTextarea-redact ${attrs.checkUrl!=null?' jenkins-input validated':''}"
<textarea id="${id}" hidden="hidden" name="${name}" placeholder="${placeholder}" rows="10"
class="secretTextarea-redact jenkins-input ${attrs.checkUrl!=null?' validated':''}"
checkUrl="${attrs.checkUrl}" checkDependsOn="${attrs.checkDependsOn}" checkMethod="${attrs.checkMethod}">
<st:out value="${value}" />
</textarea>
@@ -23,16 +23,15 @@
*/
.secret-header {
border: 1px solid #ccc;
border: 1px solid var(--input-border);
border-radius: 3px;
background: #f9f9f9;
background: var(--input-hidden-password-bg-color);
display: flex;
justify-content: space-around;
border: var(--jenkins-border-width) solid var(--input-border);
border-radius: var(--form-input-border-radius);
background: var(--input-color);
}
.secret-header:not(:only-child) {
.secret-header--expanded {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
@@ -41,11 +40,12 @@
flex-grow: 1;
display: inline-flex;
align-items: center;
padding: 1.5em 1.75em;
padding: 0 calc(var(--section-padding) / 2);
min-height: 4rem;
}
.secret-legend > svg {
margin-right: 1em;
margin-right: calc(var(--section-padding) / 2);
}
.secret-update {
@@ -53,17 +53,13 @@
}
.secret-input {
border: solid 1px #ccc;
border: solid 1px var(--input-border);
border-top: none;
border-radius: 0 0 3px 3px;
display: flex;
}
.secret-input textarea {
width: 100%;
font-family: monospace;
border: none;
padding: 1em;
font-family: var(--font-family-mono);
border-radius: 0 0 var(--form-input-border-radius)
var(--form-input-border-radius);
}
.secret * [hidden] {
@@ -29,8 +29,11 @@ Behaviour.specify(".secret", "secret-button", 0, function (e) {
}
var unhideSecretInput = function () {
var textArea = e.querySelector('textarea[hidden="hidden"]');
const header = e.querySelector(".secret-header");
header.classList.add("secret-header--expanded");
const textArea = e.querySelector('textarea[hidden="hidden"]');
textArea.removeAttribute("hidden");
textArea.focus();
};
var clearSecretValue = function () {
@@ -53,7 +53,7 @@ THE SOFTWARE.
<s:attribute name="clazz" />
</s:documentation>
<button id="${attrs.id}" name="${attrs.name ?: 'Submit'}" formNoValidate="formNoValidate"
<button id="${attrs.id}" name="${attrs.name ?: 'Submit'}" value="${attrs.value ?: '%Submit'}" formNoValidate="formNoValidate"
class="jenkins-button jenkins-submit-button ${attrs.primary != 'false' ? 'jenkins-button--primary' : ''} ${attrs.clazz}">
<j:if test="${attrs.icon != null}">
<l:icon src="${attrs.icon}" />
@@ -27,8 +27,7 @@ THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:f="/lib/form">
<l:layout permission="${app.ADMINISTER}" title="${%scriptConsole}">
<st:include page="sidepanel.jelly" />
<l:layout permission="${app.ADMINISTER}" title="${%scriptConsole}" type="one-column">
<l:breadcrumb title="${%scriptConsole}"/>
<l:main-panel>
@@ -122,7 +122,6 @@ THE SOFTWARE.
<link rel="alternate icon" href="${resURL}/favicon.ico" sizes="any" />
<link rel="apple-touch-icon" href="${resURL}/apple-touch-icon.png" sizes="180x180" />
<link rel="mask-icon" href="${resURL}/mask-icon.svg" color="#191717" />
<meta name="theme-color" content="#ffffff" />
<script src="${resURL}/scripts/behavior.js" type="text/javascript"/>
+3 -3
View File
@@ -23,7 +23,7 @@
"lint": "yarn lint:js && yarn lint:css"
},
"devDependencies": {
"@babel/cli": "7.26.4",
"@babel/cli": "7.27.0",
"@babel/core": "7.26.10",
"@babel/preset-env": "7.26.9",
"@eslint/js": "9.23.0",
@@ -45,7 +45,7 @@
"sass": "1.86.0",
"sass-loader": "16.0.5",
"style-loader": "4.0.0",
"stylelint": "16.16.0",
"stylelint": "16.17.0",
"stylelint-checkstyle-reporter": "1.0.0",
"stylelint-config-standard-scss": "14.0.0",
"webpack": "5.98.0",
@@ -68,5 +68,5 @@
"engines": {
"node": ">=20.0.0"
},
"packageManager": "yarn@4.7.0"
"packageManager": "yarn@4.8.1"
}
+3 -3
View File
@@ -73,9 +73,9 @@ THE SOFTWARE.
</issueManagement>
<properties>
<revision>2.504</revision>
<revision>2.505</revision>
<changelist>-SNAPSHOT</changelist>
<project.build.outputTimestamp>2025-03-25T14:01:20Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2025-03-31T13:10:14Z</project.build.outputTimestamp>
<!-- configuration for patch tracker plugin -->
<project.patchManagement.system>github</project.patchManagement.system>
@@ -281,7 +281,7 @@ THE SOFTWARE.
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>10.21.4</version>
<version>10.23.0</version>
</dependency>
</dependencies>
<executions>
-1
View File
@@ -309,7 +309,6 @@ $semantics: (
var(--text-color-secondary) 50%,
transparent
);
--input-hidden-password-bg-color: #f9f9f9;
--form-item-max-width: min(65vw, 1600px);
--form-item-max-width--medium: min(50vw, 1400px);
--form-item-max-width--small: min(35vw, 1200px);
+3 -4
View File
@@ -63,7 +63,7 @@ THE SOFTWARE.
<dependency>
<groupId>io.jenkins.plugins</groupId>
<artifactId>commons-lang3-api</artifactId>
<version>3.17.0-84.vb_b_938040b_078</version>
<version>3.17.0-87.v5cf526e63b_8b_</version>
</dependency>
<dependency>
<!-- RequireUpperBoundDeps between checks-api, plugin-util-api, and font-awesome-api -->
@@ -178,7 +178,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-test-harness</artifactId>
<version>2421.v8109b_b_b_70175</version>
<version>2427.v186cd47d9b_e0</version>
<scope>test</scope>
<exclusions>
<exclusion>
@@ -218,7 +218,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>cloudbees-folder</artifactId>
<version>6.991.v1d5f531726d0</version>
<version>6.999.v42253c105443</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -242,7 +242,6 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>matrix-auth</artifactId>
<!-- TODO https://github.com/jenkinsci/matrix-auth-plugin/pull/169 -->
<version>3.2.6</version>
<scope>test</scope>
</dependency>
@@ -107,6 +107,12 @@ public class DirectoryBrowserSupportTest {
@Rule public JenkinsRule j = new JenkinsRule();
private JenkinsRule.WebClient getWebClient() {
var wc = j.createWebClient();
wc.getOptions().setJavaScriptEnabled(false);
return wc;
}
/**
* Double dots that appear in file name is OK.
*/
@@ -122,7 +128,7 @@ public class DirectoryBrowserSupportTest {
j.buildAndAssertSuccess(p);
// can we see it?
j.createWebClient().goTo("job/" + p.getName() + "/ws/abc..def", "application/octet-stream");
getWebClient().goTo("job/" + p.getName() + "/ws/abc..def", "application/octet-stream");
// TODO: implement negative check to make sure we aren't serving unexpected directories.
// the following trivial attempt failed. Someone in between is normalizing.
@@ -149,7 +155,7 @@ public class DirectoryBrowserSupportTest {
p.getBuildersList().add(new Shell("mkdir abc; touch abc/def.bin"));
j.buildAndAssertSuccess(p);
try (JenkinsRule.WebClient wc = j.createWebClient()) {
try (JenkinsRule.WebClient wc = getWebClient()) {
// normal path provided by the UI succeeds
Page page = wc.goTo("job/" + p.getName() + "/ws/abc%5Cdef.bin", "application/octet-stream");
assertEquals(200, page.getWebResponse().getStatusCode());
@@ -170,7 +176,7 @@ public class DirectoryBrowserSupportTest {
j.buildAndAssertSuccess(p);
// can we see it?
j.createWebClient().goTo("job/" + p.getName() + "/ws/%e6%bc%a2%e5%ad%97.bin", "application/octet-stream");
getWebClient().goTo("job/" + p.getName() + "/ws/%e6%bc%a2%e5%ad%97.bin", "application/octet-stream");
}
@Test
@@ -190,7 +196,7 @@ public class DirectoryBrowserSupportTest {
}
});
j.buildAndAssertSuccess(p);
String text = j.createWebClient().goTo("job/" + p.getName() + "/ws/**/*.java").asNormalizedText();
String text = getWebClient().goTo("job/" + p.getName() + "/ws/**/*.java").asNormalizedText();
assertTrue(text, text.contains("X.java"));
assertTrue(text, text.contains("XTest.java"));
assertFalse(text, text.contains("pom.xml"));
@@ -205,7 +211,7 @@ public class DirectoryBrowserSupportTest {
p.getPublishersList().add(new ArtifactArchiver("*", "", true));
j.buildAndAssertSuccess(p);
HtmlPage page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/");
HtmlPage page = getWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/");
Page download = page.getAnchorByHref("./*zip*/archive.zip").click();
File zipfile = download((UnexpectedPage) download);
@@ -231,7 +237,7 @@ public class DirectoryBrowserSupportTest {
p.getPublishersList().add(new ArtifactArchiver("*", "", true));
j.buildAndAssertSuccess(p);
HtmlPage page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/");
HtmlPage page = getWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/");
Page downloadPage = page.getAnchorByHref("artifact.out").click();
assertEquals(content, downloadPage.getWebResponse().getContentAsString());
}
@@ -254,7 +260,7 @@ public class DirectoryBrowserSupportTest {
p.getPublishersList().add(new ArtifactArchiver("*", "", true));
j.buildAndAssertSuccess(p);
HtmlPage page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/");
HtmlPage page = getWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/");
for (int clicks = 0; clicks < numOfClicks; clicks++) {
page.getAnchorByHref("artifact.out").click();
}
@@ -308,7 +314,7 @@ public class DirectoryBrowserSupportTest {
p.getPublishersList().add(new ArtifactArchiver("*", "", true));
j.buildAndAssertSuccess(p);
HtmlPage page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/test.html");
HtmlPage page = getWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/test.html");
for (String header : new String[]{"Content-Security-Policy", "X-WebKit-CSP", "X-Content-Security-Policy"}) {
assertEquals("Header set: " + header, DirectoryBrowserSupport.DEFAULT_CSP_VALUE, page.getWebResponse().getResponseHeaderValue(header));
}
@@ -317,7 +323,7 @@ public class DirectoryBrowserSupportTest {
String initialValue = System.getProperty(propName);
try {
System.setProperty(propName, "");
page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/test.html");
page = getWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/test.html");
List<String> headers = page.getWebResponse().getResponseHeaders().stream().map(NameValuePair::getName).collect(Collectors.toList());
for (String header : new String[]{"Content-Security-Policy", "X-WebKit-CSP", "X-Content-Security-Policy"}) {
assertThat(headers, not(hasItem(header)));
@@ -351,7 +357,7 @@ public class DirectoryBrowserSupportTest {
p.setScm(new SingleFileSCM("f", "Hello world!"));
p.getPublishersList().add(new ArtifactArchiver("f"));
j.buildAndAssertSuccess(p);
HtmlPage page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/");
HtmlPage page = getWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/");
Page download = page.getAnchorByText("f").click();
assertEquals("Hello world!", download.getWebResponse().getContentAsString());
}
@@ -614,7 +620,7 @@ public class DirectoryBrowserSupportTest {
j.buildAndAssertSuccess(p);
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
{ // workspace root must be reachable (regular case)
Page page = wc.goTo(p.getUrl() + "ws/", null);
@@ -759,7 +765,7 @@ public class DirectoryBrowserSupportTest {
j.buildAndAssertSuccess(p);
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
// the pattern allow us to search inside the files / folders,
@@ -822,7 +828,7 @@ public class DirectoryBrowserSupportTest {
j.buildAndAssertSuccess(p);
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
{ // workspace root must be reachable (regular case)
Page page = wc.goTo(p.getUrl() + "ws/", null);
@@ -975,7 +981,7 @@ public class DirectoryBrowserSupportTest {
c3.mkdirs();
c3.child("to_secrets3").symlinkTo(secretsFolder.getAbsolutePath(), TaskListener.NULL);
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
{
Page zipPage = wc.goTo(p.getUrl() + "ws/*zip*/ws.zip", null);
@@ -1042,7 +1048,7 @@ public class DirectoryBrowserSupportTest {
j.buildAndAssertSuccess(p);
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
{ // workspace root must be reachable (regular case)
Page page = wc.goTo(p.getUrl() + "ws/", null);
@@ -1111,7 +1117,7 @@ public class DirectoryBrowserSupportTest {
String content = "random data provided as fixed value";
Files.writeString(targetTmpPath, content, StandardCharsets.UTF_8);
try (JenkinsRule.WebClient wc = j.createWebClient()) {
try (JenkinsRule.WebClient wc = getWebClient()) {
wc.setThrowExceptionOnFailingStatusCode(false);
HtmlPage page = wc.goTo("userContent/" + targetTmpPath.toAbsolutePath() + "/*view*");
assertEquals(404, page.getWebResponse().getStatusCode());
@@ -1133,7 +1139,7 @@ public class DirectoryBrowserSupportTest {
});
assertEquals(Result.SUCCESS, p.scheduleBuild2(0).get().getResult());
String text = j.createWebClient().goTo("job/" + p.getName() + "/ws/").asNormalizedText();
String text = getWebClient().goTo("job/" + p.getName() + "/ws/").asNormalizedText();
assertTrue(text, text.contains("anotherDir"));
assertFalse(text, text.contains("subdir"));
}
@@ -1163,7 +1169,7 @@ public class DirectoryBrowserSupportTest {
assertEquals(Result.SUCCESS, p.scheduleBuild2(0).get().getResult());
String text = j.createWebClient().goTo("job/" + p.getName() + "/ws/**/*.txt").asNormalizedText();
String text = getWebClient().goTo("job/" + p.getName() + "/ws/**/*.txt").asNormalizedText();
assertTrue(text, text.contains("one.txt"));
assertTrue(text, text.contains("two.txt"));
assertFalse(text, text.contains("three.txt"));
@@ -1192,7 +1198,7 @@ public class DirectoryBrowserSupportTest {
});
assertEquals(Result.SUCCESS, p.scheduleBuild2(0).get().getResult());
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
Page page = wc.goTo(p.getUrl() + "ws/anotherDir/", null);
@@ -1222,7 +1228,7 @@ public class DirectoryBrowserSupportTest {
});
assertEquals(Result.SUCCESS, p.scheduleBuild2(0).get().getResult());
String text = j.createWebClient().goTo("job/" + p.getName() + "/ws/*plain*", "text/plain").getWebResponse().getContentAsString();
String text = getWebClient().goTo("job/" + p.getName() + "/ws/*plain*", "text/plain").getWebResponse().getContentAsString();
assertTrue(text, text.contains("anotherDir"));
assertFalse(text, text.contains("subdir"));
}
@@ -1255,7 +1261,7 @@ public class DirectoryBrowserSupportTest {
});
assertEquals(Result.SUCCESS, p.scheduleBuild2(0).get().getResult());
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
//http://localhost:54407/jenkins/job/test0/ws/**/*.txt/*zip*/glob.zip
@@ -1308,7 +1314,7 @@ public class DirectoryBrowserSupportTest {
});
assertEquals(Result.SUCCESS, p.scheduleBuild2(0).get().getResult());
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
Page zipPage = wc.goTo("job/" + p.getName() + "/ws/**/*.txt/*zip*/glob.zip", null);
@@ -1329,7 +1335,7 @@ public class DirectoryBrowserSupportTest {
Files.writeString(testFile.toPath(), content, StandardCharsets.UTF_8);
JenkinsRule.WebClient wc = j.createWebClient().withThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = getWebClient().withThrowExceptionOnFailingStatusCode(false);
Page page = wc.goTo("userContent/test.txt/*view*", null);
MatcherAssert.assertThat(page.getWebResponse().getStatusCode(), equalTo(200));
@@ -59,6 +59,12 @@ public class FileParameterValueTest {
@Rule
public TemporaryFolder tmp = new TemporaryFolder();
private JenkinsRule.WebClient getWebClient() {
var wc = j.createWebClient();
wc.getOptions().setJavaScriptEnabled(false);
return wc;
}
@Test
@Issue("SECURITY-1074")
public void fileParameter_cannotCreateFile_outsideOfBuildFolder() throws Exception {
@@ -85,7 +91,7 @@ public class FileParameterValueTest {
assertThat(root.child("root-level.txt").exists(), equalTo(false));
// ensure also the file is not reachable by request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
checkUrlNot200AndNotContains(wc, build.getUrl() + "parameters/parameter/..%2F..%2F..%2F..%2F..%2Froot-level.txt/uploaded-file.txt", uploadedContent);
@@ -125,7 +131,7 @@ public class FileParameterValueTest {
assertThat(root.child("pwned").exists(), equalTo(false));
// ensure also the file is not reachable by request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
}
@@ -152,7 +158,7 @@ public class FileParameterValueTest {
assertThat(root.child("pwned").exists(), equalTo(false));
// ensure also the file is not reachable by request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
}
@@ -190,7 +196,7 @@ public class FileParameterValueTest {
assertThat(root.child("root-level.txt").exists(), equalTo(false));
// ensure also the file is not reachable by request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
checkUrlNot200AndNotContains(wc, build.getUrl() + "parameters/parameter/..\\..\\..\\..\\..\\root-level.txt/uploaded-file.txt", uploadedContent);
@@ -218,7 +224,7 @@ public class FileParameterValueTest {
assertThat(build.getResult(), equalTo(Result.FAILURE));
// ensure also the file is not reachable by request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
checkUrlNot200AndNotContains(wc, build.getUrl() + "parameters/parameter/uploaded-file.txt", uploadedContent);
@@ -246,7 +252,7 @@ public class FileParameterValueTest {
assertThat(build.getResult(), equalTo(Result.FAILURE));
// ensure also the file is not reachable by request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
checkUrlNot200AndNotContains(wc, build.getUrl() + "parameters/uploaded-file.txt", uploadedContent);
@@ -281,7 +287,7 @@ public class FileParameterValueTest {
assertThat(root.child("root-level.txt").readToString(), equalTo(initialContent));
// ensure also the file is not reachable by request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
checkUrlNot200AndNotContains(wc, build.getUrl() + "parameters/parameter/..%2F..%2F..%2F..%2F..%2Froot-level.txt/uploaded-file.txt", uploadedContent);
@@ -317,7 +323,7 @@ public class FileParameterValueTest {
assertTrue(build.getWorkspace().child("parent").child("child2.txt").exists());
// and reachable using request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
HtmlPage workspacePage = wc.goTo(p.getUrl() + "ws");
String workspaceContent = workspacePage.getWebResponse().getContentAsString();
assertThat(workspaceContent, allOf(
@@ -351,7 +357,7 @@ public class FileParameterValueTest {
assertTrue(build.getWorkspace().child("weird..name.txt").exists());
// and reachable using request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
HtmlPage workspacePage = wc.goTo(p.getUrl() + "ws");
String workspaceContent = workspacePage.getWebResponse().getContentAsString();
assertThat(workspaceContent, containsString("weird..name.txt"));
@@ -379,7 +385,7 @@ public class FileParameterValueTest {
assertTrue(build.getWorkspace().child("~name").exists());
// and reachable using request
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = getWebClient();
HtmlPage workspacePage = wc.goTo(p.getUrl() + "ws");
String workspaceContent = workspacePage.getWebResponse().getContentAsString();
assertThat(workspaceContent, containsString("~name"));
@@ -391,7 +397,8 @@ public class FileParameterValueTest {
public void contentSecurityPolicy() throws Exception {
FreeStyleProject p = j.jenkins.getItemByFullName("SECURITY-1793", FreeStyleProject.class);
HtmlPage page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/parameters/parameter/html.html/html.html");
var wc = getWebClient();
HtmlPage page = wc.goTo("job/" + p.getName() + "/lastSuccessfulBuild/parameters/parameter/html.html/html.html");
for (String header : new String[]{"Content-Security-Policy", "X-WebKit-CSP", "X-Content-Security-Policy"}) {
assertEquals("Header set: " + header, DirectoryBrowserSupport.DEFAULT_CSP_VALUE, page.getWebResponse().getResponseHeaderValue(header));
}
@@ -400,7 +407,7 @@ public class FileParameterValueTest {
String initialValue = System.getProperty(propName);
try {
System.setProperty(propName, "");
page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/parameters/parameter/html.html/html.html");
page = wc.goTo("job/" + p.getName() + "/lastSuccessfulBuild/parameters/parameter/html.html/html.html");
List<String> headers = page.getWebResponse().getResponseHeaders().stream().map(NameValuePair::getName).collect(Collectors.toList());
for (String header : new String[]{"Content-Security-Policy", "X-WebKit-CSP", "X-Content-Security-Policy"}) {
assertThat(headers, not(hasItem(header)));
@@ -0,0 +1,55 @@
package jenkins.agents;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.InboundAgentRule;
import org.jvnet.hudson.test.RealJenkinsRule;
public class InboundAgentTlsTest {
@Rule
public final RealJenkinsRule rjr = new RealJenkinsRule().https();
@Rule
public InboundAgentRule iar = new InboundAgentRule();
@Before
public void setUp() throws Throwable {
rjr.startJenkins();
}
@Test
public void webSocketNoCertificateCheck() throws Throwable {
var options = InboundAgentRule.Options
.newBuilder()
.webSocket()
.noCertificateCheck();
iar.createAgent(rjr, options.build());
}
@Test
public void webSocketWithCertByValue() throws Throwable {
var options = InboundAgentRule.Options
.newBuilder()
.webSocket()
.cert(rjr.getRootCAPem());
iar.createAgent(rjr, options.build());
}
@Test
public void tcpWithNoCertificateCheck() throws Throwable {
var options = InboundAgentRule.Options
.newBuilder()
.noCertificateCheck();
iar.createAgent(rjr, options.build());
}
@Test
public void tcpWithCertByValue() throws Throwable {
var options = InboundAgentRule.Options
.newBuilder()
.cert(rjr.getRootCAPem());
iar.createAgent(rjr, options.build());
}
}
@@ -0,0 +1,62 @@
package jenkins.security;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import hudson.model.Computer;
import hudson.slaves.DumbSlave;
import java.net.URL;
import jenkins.model.Jenkins;
import org.htmlunit.HttpMethod;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
public class Security3512Test {
@Rule
public JenkinsRule j = new JenkinsRule();
@Test
@Issue("SECURITY-3512")
public void copyAgentTest() throws Exception {
Computer.EXTENDED_READ.setEnabled(true);
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
MockAuthorizationStrategy mockAuthorizationStrategy = new MockAuthorizationStrategy();
mockAuthorizationStrategy.grant(Jenkins.READ, Computer.CREATE, Computer.EXTENDED_READ).everywhere().to("alice");
mockAuthorizationStrategy.grant(Jenkins.READ, Computer.CREATE).everywhere().to("bob");
j.jenkins.setAuthorizationStrategy(mockAuthorizationStrategy);
DumbSlave agent = j.createOnlineSlave();
assertEquals(2, j.getInstance().getComputers().length);
String agentCopyURL = j.getURL() + "/computer/createItem?mode=copy&from=" + agent.getNodeName() + "&name=";
{ // with ExtendedRead permission you can copy a node
try (JenkinsRule.WebClient wc = j.createWebClient().withThrowExceptionOnFailingStatusCode(false).login("alice")) {
WebResponse rsp = wc.getPage(wc.addCrumb(new WebRequest(new URL(agentCopyURL + "aliceAgent"),
HttpMethod.POST))).getWebResponse();
assertEquals(200, rsp.getStatusCode());
assertEquals(3, j.getInstance().getComputers().length);
}
}
{ // without ExtendedRead permission you cannot copy a node
try (JenkinsRule.WebClient wc = j.createWebClient().withThrowExceptionOnFailingStatusCode(false).login("bob")) {
WebResponse rsp = wc.getPage(wc.addCrumb(new WebRequest(new URL(agentCopyURL + "bobAgent"),
HttpMethod.POST))).getWebResponse();
assertEquals(403, rsp.getStatusCode());
assertThat(rsp.getContentAsString(), containsString("bob is missing the Agent/ExtendedRead permission"));
assertEquals(3, j.getInstance().getComputers().length);
}
}
}
}
@@ -37,6 +37,7 @@ import static org.junit.Assert.assertTrue;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.cli.CopyJobCommand;
@@ -62,6 +63,7 @@ import hudson.model.ViewProperty;
import hudson.security.ACL;
import hudson.slaves.DumbSlave;
import hudson.slaves.NodeProperty;
import hudson.slaves.NodePropertyDescriptor;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;
import hudson.util.FormValidation;
@@ -70,6 +72,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -82,7 +85,10 @@ import jenkins.model.TransientActionFactory;
import jenkins.security.ExtendedReadRedaction;
import jenkins.security.ExtendedReadSecretRedaction;
import jenkins.tasks.SimpleBuildStep;
import org.htmlunit.HttpMethod;
import org.htmlunit.Page;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.htmlunit.html.DomElement;
import org.htmlunit.html.HtmlHiddenInput;
import org.htmlunit.html.HtmlInput;
@@ -195,9 +201,62 @@ public class PasswordTest {
}
}
@For({ExtendedReadRedaction.class, ExtendedReadSecretRedaction.class})
@Issue("SECURITY-3513")
@Test
public void testCopyNodeSecrets() throws Exception {
Computer.EXTENDED_READ.setEnabled(true);
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
MockAuthorizationStrategy mockAuthorizationStrategy = new MockAuthorizationStrategy();
mockAuthorizationStrategy.grant(Jenkins.READ, Computer.CREATE, Computer.CONFIGURE).everywhere().to("alice");
mockAuthorizationStrategy.grant(Jenkins.READ, Computer.CREATE, Computer.EXTENDED_READ).everywhere().to("bob");
j.jenkins.setAuthorizationStrategy(mockAuthorizationStrategy);
final DumbSlave onlineSlave = j.createOnlineSlave();
final String secretText = "t0ps3cr3td4t4_node";
final Secret encryptedSecret = Secret.fromString(secretText);
final String encryptedSecretText = encryptedSecret.getEncryptedValue();
onlineSlave.getNodeProperties().add(new NodePropertyWithSecret(encryptedSecret));
onlineSlave.save();
assertThat(readString(new File(onlineSlave.getRootDir(), "config.xml").toPath()), containsString(encryptedSecretText));
assertEquals(2, j.getInstance().getComputers().length);
String agentCopyURL = j.getURL() + "/computer/createItem?mode=copy&from=" + onlineSlave.getNodeName() + "&name=";
{ // with configure, you can copy a node containing secrets
try (JenkinsRule.WebClient wc = j.createWebClient().login("alice")) {
WebResponse rsp = wc.getPage(wc.addCrumb(new WebRequest(new URL(agentCopyURL + "aliceAgent"),
HttpMethod.POST))).getWebResponse();
assertEquals(200, rsp.getStatusCode());
assertEquals(3, j.getInstance().getComputers().length);
final Page page = wc.goTo("computer/aliceAgent/config.xml", "application/xml");
final String content = page.getWebResponse().getContentAsString();
assertThat(content, not(containsString(secretText)));
assertThat(content, containsString(encryptedSecretText));
assertThat(content, containsString("<secret>" + encryptedSecretText + "</secret>"));
}
}
{ // without configure, you cannot copy a node containing secrets
try (JenkinsRule.WebClient wc = j.createWebClient().withThrowExceptionOnFailingStatusCode(false).login("bob")) {
WebResponse rsp = wc.getPage(wc.addCrumb(new WebRequest(new URL(agentCopyURL + "bobAgent"),
HttpMethod.POST))).getWebResponse();
assertEquals(403, rsp.getStatusCode());
assertThat(rsp.getContentAsString(), containsString("May not copy " + onlineSlave.getNodeName() + " as it contains secrets"));
assertEquals(3, j.getInstance().getComputers().length);
}
}
}
public static class NodePropertyWithSecret extends NodeProperty<Node> {
private final Secret secret;
@DataBoundConstructor
public NodePropertyWithSecret(Secret secret) {
this.secret = secret;
}
@@ -205,6 +264,11 @@ public class PasswordTest {
public Secret getSecret() {
return secret;
}
@Extension
public static class DescriptorImpl extends NodePropertyDescriptor {
}
}
@For({ExtendedReadRedaction.class, ExtendedReadSecretRedaction.class})
@@ -0,0 +1,6 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:entry title="Secret" field="secret">
<f:password/>
</f:entry>
</j:jelly>
+5 -5
View File
@@ -289,7 +289,7 @@ THE SOFTWARE.
<!-- detached after 1.535 -->
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>matrix-auth</artifactId>
<version>3.2.5</version>
<version>3.2.6</version>
<type>hpi</type>
</artifactItem>
<artifactItem>
@@ -382,7 +382,7 @@ THE SOFTWARE.
<!-- dependency of jackson2-api -->
<groupId>io.jenkins.plugins</groupId>
<artifactId>snakeyaml-api</artifactId>
<version>2.3-123.v13484c65210a_</version>
<version>2.3-125.v4d77857a_b_402</version>
<type>hpi</type>
</artifactItem>
@@ -390,7 +390,7 @@ THE SOFTWARE.
<!-- dependency of script-security and workflow-support -->
<groupId>io.jenkins.plugins</groupId>
<artifactId>caffeine-api</artifactId>
<version>3.2.0-161.v691ef352cee1</version>
<version>3.2.0-166.v72a_6d74b_870f</version>
<type>hpi</type>
</artifactItem>
@@ -505,14 +505,14 @@ THE SOFTWARE.
<!-- dependency of scm-api -->
<groupId>io.jenkins.plugins</groupId>
<artifactId>asm-api</artifactId>
<version>9.7.1-97.v4cc844130d97</version>
<version>9.8-135.vb_2239d08ee90</version>
<type>hpi</type>
</artifactItem>
<artifactItem>
<!-- dependency of bootstrap5-api, checks-api, commons-text-api, echarts-api, font-awesome-api, jquery3-api, and plugin-util-api -->
<groupId>io.jenkins.plugins</groupId>
<artifactId>commons-lang3-api</artifactId>
<version>3.17.0-84.vb_b_938040b_078</version>
<version>3.17.0-87.v5cf526e63b_8b_</version>
<type>hpi</type>
</artifactItem>
<artifactItem>
@@ -92,8 +92,10 @@ public class Jetty12EE9Provider implements Provider {
}
@Override
public void sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException {
session().getRemote().sendPartialBytes(partialByte, isLast);
public Future<Void> sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException {
CompletableFuture<Void> f = new CompletableFuture<>();
session().getRemote().sendPartialBytes(partialByte, isLast, new WriteCallbackImpl(f));
return f;
}
@Override
@@ -65,7 +65,7 @@ interface Provider {
Future<Void> sendBinary(ByteBuffer data) throws IOException;
void sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException;
Future<Void> sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException;
Future<Void> sendText(String text) throws IOException;
+10 -10
View File
@@ -15,9 +15,9 @@ __metadata:
languageName: node
linkType: hard
"@babel/cli@npm:7.26.4":
version: 7.26.4
resolution: "@babel/cli@npm:7.26.4"
"@babel/cli@npm:7.27.0":
version: 7.27.0
resolution: "@babel/cli@npm:7.27.0"
dependencies:
"@jridgewell/trace-mapping": "npm:^0.3.25"
"@nicolo-ribaudo/chokidar-2": "npm:2.1.8-no-fsevents.3"
@@ -38,7 +38,7 @@ __metadata:
bin:
babel: ./bin/babel.js
babel-external-helpers: ./bin/babel-external-helpers.js
checksum: 10c0/f2d4fc3c4a34dd3001e3bd7084b78b38211003c36afaf2dc8fedf4565c0442bd59b1c64a9f91a0b7b2450e089123f197e09577ae50dc994307c3348b310ce34c
checksum: 10c0/b68309b4b2488a3b5ef1d119cbd36bee0e8f140979e889e58b3f9cd345b9352fdfbb0f6db709bd885219f387183a01be33e6fcdeacf2cf23efbea362cae68707
languageName: node
linkType: hard
@@ -4349,7 +4349,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "jenkins-ui@workspace:."
dependencies:
"@babel/cli": "npm:7.26.4"
"@babel/cli": "npm:7.27.0"
"@babel/core": "npm:7.26.10"
"@babel/preset-env": "npm:7.26.9"
"@eslint/js": "npm:9.23.0"
@@ -4376,7 +4376,7 @@ __metadata:
sass-loader: "npm:16.0.5"
sortablejs: "npm:1.15.6"
style-loader: "npm:4.0.0"
stylelint: "npm:16.16.0"
stylelint: "npm:16.17.0"
stylelint-checkstyle-reporter: "npm:1.0.0"
stylelint-config-standard-scss: "npm:14.0.0"
tippy.js: "npm:6.3.7"
@@ -6706,9 +6706,9 @@ __metadata:
languageName: node
linkType: hard
"stylelint@npm:16.16.0":
version: 16.16.0
resolution: "stylelint@npm:16.16.0"
"stylelint@npm:16.17.0":
version: 16.17.0
resolution: "stylelint@npm:16.17.0"
dependencies:
"@csstools/css-parser-algorithms": "npm:^3.0.4"
"@csstools/css-tokenizer": "npm:^3.0.3"
@@ -6750,7 +6750,7 @@ __metadata:
write-file-atomic: "npm:^5.0.1"
bin:
stylelint: bin/stylelint.mjs
checksum: 10c0/7884a347fbaf04215f205bb9630bce91c72a3d08ddd5aec1d1ad7ccfdff50854bb6ad995945d5d6a6a4052a1c5fadb3fd4929e8e7db4cde5a6ce0f7dbe537800
checksum: 10c0/0b1bb4e362babe799afc42086fdc3a5621c230a0d4ad4a947a44d14311b758bf5a0fab0dea4fef31223dde97617f43510a37480d25f9eed23e2ff71e97c33e07
languageName: node
linkType: hard