Openshift API Token生成方法

概述

openshift API的调用机制遵循OAuth 2.0机制,在调用API进行操作前需要先获取access token,然后拿着这个token再去调用相应的API。

open shift中提供了两种形式的token,一个是session token ,一个是service account token.前者有效期24小时,后者长期有效,但是后者是属于某一 namespace,而且能调用的API可能比较局限,本文两种方法都会介绍。

获取token的几种方法

Authorization Code Grant

此方法需要先向/oauth/authorize发送一个请求获取一个Authorization Code,

然后再拿着这个Authorization Code往/oauth/token发送请求获取access token。

这个方法比较麻烦,不建议使用。

Resource Owner Password Credentials Grant

Client Credentials Grant

此方法需要客户端有特别的认证。

Extension Grants

Implicit Grant

这个方法是常用的,如果你想调用openshift API,建议采用此方法

使用Session Token调用API

使用的是Implicit Grant方法

使用curl命令获取session token

curl -u username:password -kv -H "X-CSRF-Token: 1" 'https://example.test.com:8443/oauth/authorize?client_id=openshift-challenging-client&response_type=token'

username是用户名,password是密码

成功返回的信息如下:

..............

HTTP/2 302

..................

location: https://example.test.com:8443/oauth/token/implicit#access_token=asrpT-EhPSEG-0hYPk5v76MzemoxWIc0DurGqk6OnlI&expires_in=86400&scope=user%3Afull&token_type=Bearer

................

成功返回302,这是跳转代码,token就放在header中的location里面,如果curl命令中没有-v参数的话你就看不到token信息,或者你用postman来发送请求也看不到token,返回码是200,这是因为某些user-agent类型的client无法获取跳转之后的信息

在程序中获取session token

由于token是放在返回header中的location里面,所以需要去header去取

在Java程序中可以这样获取token

private static final String AUTHORIZATION = "Authorization";
private static final String LOCATION = "Location";
private static final String AUTHORIZE_PATH = "oauth/authorize?response_type=token&client_id=openshift-challenging-client";
private static final String BEFORE_TOKEN = "access_token=";
private static final String AFTER_TOKEN = "&expires";
private final OkHttpClient client;
private final OpenShiftConfig config;

private String authorize() {
    try {
        OkHttpClient.Builder builder = client.newBuilder();
 builder.interceptors().remove(this);
 OkHttpClient clone = builder.build();

 String credential = Credentials.basic(config.getUsername(), new String(config.getPassword()));
 URL url = new URL(URLUtils.join(config.getMasterUrl(), AUTHORIZE_PATH));
 Response response = clone.newCall(new Request.Builder().get().url(url).header(AUTHORIZATION, credential).build()).execute();

 response.body().close();
 response = response.priorResponse() != null ? response.priorResponse() : response;
 response = response.networkResponse() != null ? response.networkResponse() : response;
 String token = response.header(LOCATION);
 if (token == null || token.isEmpty()) {
          throw new KubernetesClientException("Unexpected response (" + response.code() + " " + response.message() + "), to the authorization request. Missing header:[" + LOCATION + "]!");
 }
        token = token.substring(token.indexOf(BEFORE_TOKEN) + BEFORE_TOKEN.length());
 token = token.substring(0, token.indexOf(AFTER_TOKEN));
 return token;
 } catch (Exception e) {
        throw KubernetesClientException.launderThrowable(e);
 }
}

由于新获取的token会在24小时后过期,所以你需要在24小时后重新生成新的token

在程序里面有两种做法:

*在调用API的时候判断返回代码如果是401: Unauthorized, 就重新生成token

*创建一个对象每隔24小时重新生成一个token,每次调用API之前只管从这个对象获取token就可以了

使用session token调用API

curl -H "Authorization: Bearer xxxxxxxxxxxxx"  -H 'Accept: application/json'   -X GET -k  https://example.test.com:8443/apis/project.openshift.io/v1/projects/default

使用Serviceaccount Token调用API

我们在default项目中创建一个serviceaccount caller,然后给这个service account赋予集群管理员的权限,这样就可以用它来调用所有的API了,最后用这个service account的token调用一个API测试是否成功。

切换到default项目

oc project default

创建serviceaccount caller

oc create serviceaccount caller

给这个service account赋予集群管理员的权限

oc policy add-cluster-role-to-user cluster-admin -z caller

获取token

oc serviceaccounts get-token caller

用刚刚获得的token来调用一个API试试

curl -H "Authorization: Bearer xxxxxxxxxxxxx"  -H 'Accept: application/json'   -X GET -k  https://example.test.com:8443/apis/project.openshift.io/v1/projects/default

上面是用oc命令行来获取serviceaccount token的,那如果要调API怎么来获取serviceaccount token呢?

我们可以用oc命令加上–loglevel=10来获取详细的调用API

oc serviceaccounts get-token ops --loglevel=10

可以看到总共发出了两条curl命令

第一条curl

curl -kv -XGET -H "Accept: application/json" -H "Authorization: Bearer xxxxxxxxx" https://example.test.com:8443/api/v1/namespaces/default/serviceaccounts/ops

用来获取ops的secret名称, 请求返回结果如下:

{"kind":"ServiceAccount","apiVersion":"v1","metadata":{"name":"ops","namespace":"default","selfLink":"/api/v1/namespaces/default/serviceaccounts/ops","uid":"3e3c5e60-e1a5-11e8-8d64-525400d56e6b","resourceVersion":"36316915","creationTimestamp":"2018-11-06T09:20:46Z"},"secrets":[{"name":"ops-token-6pn9s"},{"name":"ops-dockercfg-2wlx4"}],"imagePullSecrets":[{"name":"ops-dockercfg-2wlx4"}]}

第二条curl

curl -kv -XGET -H "Accept: application/json" -H "Authorization: Bearer xxxxxxxxx" https://example.test.com:8443/api/v1/namespaces/default/secrets/ops-token-6pn9s

获得token,但是注意要把结果反加密

{

  "kind": "Secret",

  "apiVersion": "v1",

  "metadata": {

........

    }

  },

  "data": {

    "ca.crt": "..........",

    "namespace": "ZGVmYXVsdA==",

    "service-ca.crt": "............",

    "token": "ZXlKaGJHY........RWTWFZeGg2LVhoR1E="

  },

  "type": "kubernetes.io/service-account-token"

反加密token, 获得的token才是真正的token

echo "ZXlKaGJHY........RWTWFZeGg2LVhoR1E=" | base64 --decode

猜你喜欢

转载自blog.csdn.net/haohzhang/article/details/86580119
今日推荐