2525package hudson .model ;
2626
2727import com .thoughtworks .xstream .converters .basic .AbstractSingleValueConverter ;
28+ import hudson .Extension ;
2829import hudson .Util ;
30+ import hudson .diagnosis .OldDataMonitor ;
31+ import hudson .model .listeners .ItemListener ;
2932import hudson .security .ACL ;
33+ import hudson .util .Secret ;
3034import jakarta .servlet .http .HttpServletResponse ;
3135import java .io .IOException ;
36+ import java .nio .charset .StandardCharsets ;
37+ import java .security .MessageDigest ;
38+ import java .util .logging .Level ;
39+ import java .util .logging .Logger ;
40+ import jenkins .model .Jenkins ;
41+ import jenkins .model .ParameterizedJobMixIn ;
42+ import org .kohsuke .accmod .Restricted ;
43+ import org .kohsuke .accmod .restrictions .NoExternalUse ;
3244import org .kohsuke .stapler .HttpResponses ;
3345import org .kohsuke .stapler .StaplerRequest ;
3446import org .kohsuke .stapler .StaplerRequest2 ;
4759 */
4860@ Deprecated
4961public final class BuildAuthorizationToken {
50- private final String token ;
62+ private final Secret token ;
5163
64+ private transient boolean fromPlaintext ;
65+
66+ /**
67+ * @deprecated since TODO
68+ */
69+ @ Deprecated
5270 public BuildAuthorizationToken (String token ) {
71+ this .token = Secret .fromString (token );
72+ this .fromPlaintext = true ;
73+ }
74+
75+ /**
76+ * @since TODO
77+ */
78+ public BuildAuthorizationToken (Secret token ) {
5379 this .token = token ;
80+ this .fromPlaintext = false ;
5481 }
5582
5683 /**
@@ -85,7 +112,7 @@ public static void checkPermission(Job<?, ?> project, BuildAuthorizationToken to
85112 if (token != null && token .token != null ) {
86113 //check the provided token
87114 String providedToken = req .getParameter ("token" );
88- if (providedToken != null && providedToken .equals ( token . token ))
115+ if (providedToken != null && MessageDigest . isEqual ( providedToken .getBytes ( StandardCharsets . UTF_8 ), token . getToken (). getBytes ( StandardCharsets . UTF_8 ) ))
89116 return ;
90117 if (providedToken != null )
91118 throw new AccessDeniedException (Messages .BuildAuthorizationToken_InvalidTokenProvided ());
@@ -110,7 +137,15 @@ public static void checkPermission(Job<?, ?> project, BuildAuthorizationToken to
110137 checkPermission (project , token , StaplerRequest .toStaplerRequest2 (req ), StaplerResponse .toStaplerResponse2 (rsp ));
111138 }
112139
140+ @ Deprecated
113141 public String getToken () {
142+ return token .getPlainText ();
143+ }
144+
145+ /**
146+ * @since TODO
147+ */
148+ public Secret getEncryptedToken () {
114149 return token ;
115150 }
116151
@@ -122,12 +157,44 @@ public boolean canConvert(Class type) {
122157
123158 @ Override
124159 public Object fromString (String str ) {
125- return new BuildAuthorizationToken (str );
160+ if (Secret .decrypt (str ) == null ) {
161+ return new BuildAuthorizationToken (str );
162+ }
163+ return new BuildAuthorizationToken (Secret .fromString (str ));
126164 }
127165
128166 @ Override
129167 public String toString (Object obj ) {
130- return ((BuildAuthorizationToken ) obj ).token ;
168+ final BuildAuthorizationToken bat = (BuildAuthorizationToken ) obj ;
169+ // We assume this only gets called when re-saving to its usual destination, so let's clear the in-memory state:
170+ bat .fromPlaintext = false ;
171+ return bat .token .getEncryptedValue ();
172+ }
173+ }
174+
175+ @ Extension
176+ @ Restricted (NoExternalUse .class )
177+ public static class ItemListenerImpl extends ItemListener {
178+ private static final Logger LOGGER = Logger .getLogger (ItemListenerImpl .class .getName ());
179+
180+ @ Override
181+ public void onUpdated (Item item ) {
182+ if (item instanceof ParameterizedJobMixIn .ParameterizedJob job ) {
183+ BuildAuthorizationToken bat = job .getAuthToken ();
184+ if (bat != null ) {
185+ if (bat .fromPlaintext ) {
186+ OldDataMonitor .report (item , "2.528.3 / 2.541" );
187+ LOGGER .log (Level .FINE , "Reporting " + item .getFullName ());
188+ } else {
189+ LOGGER .log (Level .FINE , "Skipping reporting of " + item .getFullName ());
190+ }
191+ }
192+ }
193+ }
194+
195+ @ Override
196+ public void onLoaded () {
197+ Jenkins .get ().getAllItems (ParameterizedJobMixIn .ParameterizedJob .class ).forEach (this ::onUpdated );
131198 }
132199 }
133200}
0 commit comments