OpenShift 如何獲取bearer Token以便進行各種API呼叫
阿新 • • 發佈:2018-12-06
Openshift 需要通過bearer token的方式和API進行呼叫,比如基於Postman就可以瞭解到,輸入bearer token後
1.如何獲取Bearer Token
但Bearer Token如何獲取是個巨大的問題,一般來說有兩種方式
1.基於oc命令列,如
[[email protected] ~]# oc login -u admin Logged into "https://master.example.com:8443" as "admin" using existing credentials. You have access to the following projects and canswitch between them with 'oc project <projectname>': * default kube-public kube-service-catalog kube-system management-infra openshift openshift-ansible-service-broker openshift-console openshift-infra openshift-logging openshift-monitoring openshift-node openshift-sdn openshift-template-service-broker openshift-web-console scdf Using project "default". [[email protected] ~]# oc whoami -t 9GLqCn9yL61TyzRjidM2GRgL-S10z0JSato9Puie70I
2.基於curl命令
[[email protected] ~]# curl -u admin:welcome1 -kv -H "X-CSRF-Token: xxx" 'https://master.example.com:8443/oauth/authorize?client_id=openshift-challenging-client&response_type=token' * About to connect() to master.example.com port 8443 (#0) * Trying 192.168.56.103... * Connected to master.example.com (192.168.56.103) port 8443 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * skipping SSL peer certificate verification * NSS: client certificate not found (nickname not specified) * SSL connection using TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 * Server certificate: * subject: CN=172.30.0.1 * start date: Nov 30 05:29:38 2018 GMT * expire date: Nov 29 05:29:39 2020 GMT * common name: 172.30.0.1 * issuer: [email protected]1543555777 * Server auth using Basic with user 'admin' > GET /oauth/authorize?client_id=openshift-challenging-client&response_type=token HTTP/1.1 > Authorization: Basic YWRtaW46d2VsY29tZTE= > User-Agent: curl/7.29.0 > Host: master.example.com:8443 > Accept: */* > X-CSRF-Token: xxx > < HTTP/1.1 302 Found < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Expires: Fri, 01 Jan 1990 00:00:00 GMT < Location: https://master.example.com:8443/oauth/token/implicit#access_token=iVwykQc-qqsO245VJ9TIZq_lIL31G1mTM2GJHTPFfkI&expires_in=86400&scope=user%3Afull&token_type=Bearer < Pragma: no-cache < Set-Cookie: ssn=MTU0NDAyNDU1OXxnZV9UaWN5QlpFZ2RULW5vY3o2dVp4SU5WVWZkbWxNd0xfUnFCVzlmRndBSS1Wb2JzY3ZJZHFYb1BPWDNqTWVMV2FjbkJ0bmtlemRMMnpDZ3FSLWUtb0lieVBJQjF0dS1nSWJiZUJrYlFLSngxYVZBa085MUN3VVJkZHJyM2FiNjU1MWkwa3RwcGtHdmJvSmhreWpfRW1MQlFuanYyeEdTcTAybDVuREtEcl9mMHhlXzVYdE5LdG5vNHpKa2QxeGMzczRKRHhzOXzT_k_wyIvwJz72RH5SJor7WYJ3lasYsoVFcdQ6phk75g==; Path=/; HttpOnly; Secure < Date: Wed, 05 Dec 2018 15:42:39 GMT < Content-Length: 0 < * Connection #0 to host master.example.com left intact
一直想通過rest去掉通,嘗試很久,最後得到的是如下錯誤
You have reached this page by following a redirect Location header from an OAuth authorize request. If a response_type=token parameter was passed to the /authorize endpoint, that requested an "Implicit Grant" OAuth flow (see https://tools.ietf.org/html/rfc6749#section-4.2). That flow requires the access token to be returned in the fragment portion of a redirect header. Rather than following the redirect here, you can obtain the access token from the Location header (see https://tools.ietf.org/html/rfc6749#section-4.2.2): 1. Parse the URL in the Location header and extract the fragment portion 2. Parse the fragment using the "application/x-www-form-urlencoded" format 3. The access_token parameter contains the granted OAuth access token
解決辦法:
通過執行一個java程式,通過後端的shell去獲取,程式碼如下:
import java.io.InputStreamReader; public class getToken { public void getocpToken() { try { //Process process = Runtime.getRuntime().exec("curl -u admin:welcome1 -kv -H \"X-CSRF-Token: xxx\" 'https://master.example.com:8443/oauth/authorize?client_id=openshift-challenging-client&response_type=token'"); Process process = Runtime.getRuntime().exec("/root/curl.sh"); BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ""; while ((line = input.readLine()) != null) { System.out.println(line); } input.close(); } catch (Exception e){ e.printStackTrace(); } } public static void main(String[] args) { // TODO Auto-generated method stub getToken sample = new getToken(); sample.getocpToken(); } }
簡單說就是呼叫了curl.sh指令碼,這個指令碼是長下面這個樣的
[[email protected] ~]# cat curl.sh curl -u admin:welcome1 -kv --silent -H "X-CSRF-Token: xxx" 'https://master.example.com:8443/oauth/authorize?client_id=openshift-challenging-client&response_type=token' 2>&1 | grep access_token | awk -F '=' '{print $2}' | awk -F '&' '{print $1}'
執行結果如下:
[[email protected] ~]# java getToken oWcKCjuSfbDaJqbLNeLCP67GuR-lAXmjSPyBplWRbvE
這種方式最大的好處是通過http去獲取,這樣不需要依賴於oc等命令和環境變數,正是因為通過http,而且用curl,所以也可以進行容器化,在容器中執行。
2.通過程式碼去刪除Pod
需要注意事項
- 搞定免證書的SSL呼叫
- 傳入bearer token
一切就很順利了,貼一下程式碼
HttpDemo.java
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.LinkedHashMap; import java.util.Map; import javax.net.ssl.HttpsURLConnection; import org.apache.commons.codec.binary.Base64; public class HttpDemo { private static final String SYS_VULLN_URL_JSON="https://master.example.com:8443/api/v1/namespaces/scdf/pods/kafka-broker-1-9qdqn"; public static void httpGet(){ StringBuffer tempStr = new StringBuffer(); String responseContent=""; HttpURLConnection conn = null; try { URL url = new URL(SYS_VULLN_URL_JSON); if("https".equalsIgnoreCase(url.getProtocol())){ SslUtils.ignoreSsl(); } HttpsURLConnection https = (HttpsURLConnection)url.openConnection(); https.setRequestMethod("DELETE"); https.setRequestProperty("Authorization", "Bearer 9GLqCn9yL61TyzRjidM2GRgL-S10z0JSato9Puie70I"); String result = getReturn(https); System.out.println(result); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch(Exception e){ e.printStackTrace(); } } /** * Trust every server - dont check for any certificate */ public static String getReturn(HttpURLConnection connection) throws IOException{ StringBuffer buffer = new StringBuffer(); try(InputStream inputStream = connection.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader);){ String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } String result = buffer.toString(); return result; } } private static void printResponseHeader(HttpURLConnection http) throws UnsupportedEncodingException { Map<String, String> header = getHttpResponseHeader(http); for (Map.Entry<String, String> entry : header.entrySet()) { String key = entry.getKey() != null ? entry.getKey() + ":" : ""; System.out.println(key + entry.getValue()); } } private static Map<String, String> getHttpResponseHeader( HttpURLConnection http) throws UnsupportedEncodingException { Map<String, String> header = new LinkedHashMap<String, String>(); for (int i = 0;; i++) { String mine = http.getHeaderField(i); if (mine == null) break; header.put(http.getHeaderFieldKey(i), mine); } return header; } public static void main(String[] args) { httpGet(); } }
SslUtils.java
import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class SslUtils { private static void trustAllHttpsCertificates() throws Exception { TrustManager[] trustAllCerts = new TrustManager[1]; TrustManager tm = new miTM(); trustAllCerts[0] = tm; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, null); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } static class miTM implements TrustManager,X509TrustManager { public X509Certificate[] getAcceptedIssuers() { return null; } public boolean isServerTrusted(X509Certificate[] certs) { return true; } public boolean isClientTrusted(X509Certificate[] certs) { return true; } public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { return; } public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException { return; } } /** * 忽略HTTPS請求的SSL證書,必須在openConnection之前呼叫 * @throws Exception */ public static void ignoreSsl() throws Exception{ HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { return true; } }; trustAllHttpsCertificates(); HttpsURLConnection.setDefaultHostnameVerifier(hv); } }
好了,有了token,又不需要證書,大家就可以愉快的玩耍了。