OpenShift 如何获取bearer Token以便进行各种API调用

Posted ericnie的技术博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenShift 如何获取bearer Token以便进行各种API调用相关的知识,希望对你有一定的参考价值。

Openshift 需要通过bearer token的方式和API进行调用,比如基于Postman就可以了解到,输入bearer token后

1.如何获取Bearer Token

但Bearer Token如何获取是个巨大的问题,一般来说有两种方式

1.基于oc命令行,如

[root@master ~]# oc login -u admin
Logged into "https://master.example.com:8443" as "admin" using existing credentials.

You have access to the following projects and can switch 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".
[root@master ~]# oc whoami -t
9GLqCn9yL61TyzRjidM2GRgL-S10z0JSato9Puie70I

2.基于curl命令

[root@node1 ~]# 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: CN=openshift-signer@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脚本,这个脚本是长下面这个样的

[root@master ~]# 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}\'

 

运行结果如下:

[root@master ~]# 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,又不需要证书,大家就可以愉快的玩耍了。

 

以上是关于OpenShift 如何获取bearer Token以便进行各种API调用的主要内容,如果未能解决你的问题,请参考以下文章

离子存储获取返回一个承诺“Bearer [object Promise]”如何返回一个值并将其用作授权令牌?

如何在 openshift 中使用 keycloak 和 spring 读取所有用户?

golang 为go-twitter获取Bearer Token功能

从 OWIN 中的 OAuth Bearer Token 获取 IPrincipal

如何正确使用 Bearer 代币?

使用NodeJS验证包含“Bearer:”的JWT标记字符串