Jenkins(2020年及以后版本,2.260以上)安装后,插件下载时失败,网上找了各种解决方法,修改jenkins插件的下载源地址:
找到菜单Manage Jenkins → Manage Plugins → Advanced → Update Site,
把URL改为 https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
或把默认地址 https://updates.jenkins.io/update-center.json 的https改为http再重启。
我把这些方法都试了以后,下载插件还是报错,心拨凉拨凉的。学技术的都最怕遇到环境问题,一个小环境问题可能要倒腾好几天。
嘿嘿,在我刚要选择投降放弃时,柳暗花明又一村,摸索到了以下Jenkins安装插件失败的另一种解决方法。
(Update Site的默认URL不需要动)
1.报错图:
报错的首行提示:sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
报错原因:访问https的插件地址因为安全证书问题而报错。
2.解决方案:
1.先编译如下文件InstallCert.java
命令:javac InstallCert.java;
2.再运行InstallCert类,命令:java InstallCert <hostname>;出现提示后按1,回车。会生成jssecacerts 文件。
PS:此处hostname 为 mirrors.tuna.tsinghua.edu.cn,国内jenkins下载插件的地址会重定向到清华大学提供的镜像文件库。
3.然后将生成的 jssecacerts 文件,拷贝到jdk中,目录位置:%JAVA_HOME%jrelibsecurity
(例如 D:Program FilesJavajdk1.8.0_71jrelibsecurity)
4.最后重新启动jenkins,证书才能生效。
文件:InstallCert.java
1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of Sun Microsystems nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 import java.io.BufferedReader; 33 import java.io.File; 34 import java.io.FileInputStream; 35 import java.io.FileOutputStream; 36 import java.io.InputStream; 37 import java.io.InputStreamReader; 38 import java.io.OutputStream; 39 import java.security.KeyStore; 40 import java.security.MessageDigest; 41 import java.security.cert.CertificateException; 42 import java.security.cert.X509Certificate; 43 44 import javax.net.ssl.SSLContext; 45 import javax.net.ssl.SSLException; 46 import javax.net.ssl.SSLSocket; 47 import javax.net.ssl.SSLSocketFactory; 48 import javax.net.ssl.TrustManager; 49 import javax.net.ssl.TrustManagerFactory; 50 import javax.net.ssl.X509TrustManager; 51 52 public class InstallCert { 53 54 public static void main(String[] args) throws Exception { 55 String host; 56 int port; 57 char[] passphrase; 58 if ((args.length == 1) || (args.length == 2)) { 59 String[] c = args[0].split(":"); 60 host = c[0]; 61 port = (c.length == 1) ? 443 : Integer.parseInt(c[1]); 62 String p = (args.length == 1) ? "changeit" : args[1]; 63 passphrase = p.toCharArray(); 64 } else { 65 System.out 66 .println("Usage: java InstallCert <host>[:port] [passphrase]"); 67 return; 68 } 69 70 File file = new File("jssecacerts"); 71 if (file.isFile() == false) { 72 char SEP = File.separatorChar; 73 File dir = new File(System.getProperty("java.home") + SEP + "lib" 74 + SEP + "security"); 75 file = new File(dir, "jssecacerts"); 76 if (file.isFile() == false) { 77 file = new File(dir, "cacerts"); 78 } 79 } 80 System.out.println("Loading KeyStore " + file + "..."); 81 InputStream in = new FileInputStream(file); 82 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 83 ks.load(in, passphrase); 84 in.close(); 85 86 SSLContext context = SSLContext.getInstance("TLS"); 87 TrustManagerFactory tmf = TrustManagerFactory 88 .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 89 tmf.init(ks); 90 X509TrustManager defaultTrustManager = (X509TrustManager) tmf 91 .getTrustManagers()[0]; 92 SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); 93 context.init(null, new TrustManager[] { tm }, null); 94 SSLSocketFactory factory = context.getSocketFactory(); 95 96 System.out 97 .println("Opening connection to " + host + ":" + port + "..."); 98 SSLSocket socket = (SSLSocket) factory.createSocket(host, port); 99 socket.setSoTimeout(10000); 100 try { 101 System.out.println("Starting SSL handshake..."); 102 socket.startHandshake(); 103 socket.close(); 104 System.out.println(); 105 System.out.println("No errors, certificate is already trusted"); 106 } catch (SSLException e) { 107 System.out.println(); 108 e.printStackTrace(System.out); 109 } 110 111 X509Certificate[] chain = tm.chain; 112 if (chain == null) { 113 System.out.println("Could not obtain server certificate chain"); 114 return; 115 } 116 117 BufferedReader reader = new BufferedReader(new InputStreamReader( 118 System.in)); 119 120 System.out.println(); 121 System.out.println("Server sent " + chain.length + " certificate(s):"); 122 System.out.println(); 123 MessageDigest sha1 = MessageDigest.getInstance("SHA1"); 124 MessageDigest md5 = MessageDigest.getInstance("MD5"); 125 for (int i = 0; i < chain.length; i++) { 126 X509Certificate cert = chain[i]; 127 System.out.println(" " + (i + 1) + " Subject " 128 + cert.getSubjectDN()); 129 System.out.println(" Issuer " + cert.getIssuerDN()); 130 sha1.update(cert.getEncoded()); 131 System.out.println(" sha1 " + toHexString(sha1.digest())); 132 md5.update(cert.getEncoded()); 133 System.out.println(" md5 " + toHexString(md5.digest())); 134 System.out.println(); 135 } 136 137 System.out 138 .println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); 139 String line = reader.readLine().trim(); 140 int k; 141 try { 142 k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; 143 } catch (NumberFormatException e) { 144 System.out.println("KeyStore not changed"); 145 return; 146 } 147 148 X509Certificate cert = chain[k]; 149 String alias = host + "-" + (k + 1); 150 ks.setCertificateEntry(alias, cert); 151 152 OutputStream out = new FileOutputStream("jssecacerts"); 153 ks.store(out, passphrase); 154 out.close(); 155 156 System.out.println(); 157 System.out.println(cert); 158 System.out.println(); 159 System.out 160 .println("Added certificate to keystore 'jssecacerts' using alias '" 161 + alias + "'"); 162 } 163 164 private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray(); 165 166 private static String toHexString(byte[] bytes) { 167 StringBuilder sb = new StringBuilder(bytes.length * 3); 168 for (int b : bytes) { 169 b &= 0xff; 170 sb.append(HEXDIGITS[b >> 4]); 171 sb.append(HEXDIGITS[b & 15]); 172 sb.append(' '); 173 } 174 return sb.toString(); 175 } 176 177 private static class SavingTrustManager implements X509TrustManager { 178 179 private final X509TrustManager tm; 180 private X509Certificate[] chain; 181 182 SavingTrustManager(X509TrustManager tm) { 183 this.tm = tm; 184 } 185 186 public X509Certificate[] getAcceptedIssuers() { 187 throw new UnsupportedOperationException(); 188 } 189 190 public void checkClientTrusted(X509Certificate[] chain, String authType) 191 throws CertificateException { 192 throw new UnsupportedOperationException(); 193 } 194 195 public void checkServerTrusted(X509Certificate[] chain, String authType) 196 throws CertificateException { 197 this.chain = chain; 198 tm.checkServerTrusted(chain, authType); 199 } 200 } 201 202 }