|
12 | 12 | */ |
13 | 13 | package io.kubernetes.client.util.authenticators; |
14 | 14 |
|
| 15 | +import com.google.auth.oauth2.AccessToken; |
| 16 | +import com.google.auth.oauth2.GoogleCredentials; |
15 | 17 | import com.google.gson.JsonObject; |
16 | 18 | import com.google.gson.JsonParser; |
17 | 19 | import io.kubernetes.client.util.KubeConfig; |
@@ -40,17 +42,25 @@ public class GCPAuthenticator implements Authenticator { |
40 | 42 | static final String EXPIRY = "expiry"; |
41 | 43 | static final String CMD_ARGS = "cmd-args"; |
42 | 44 | static final String CMD_PATH = "cmd-path"; |
| 45 | + static final String SCOPES = "scopes"; |
| 46 | + static final String[] DEFAULT_SCOPES = |
| 47 | + new String[] { |
| 48 | + "https://www.googleapis.com/auth/cloud-platform", |
| 49 | + "https://www.googleapis.com/auth/userinfo.email" |
| 50 | + }; |
43 | 51 |
|
44 | 52 | private static final Logger log = LoggerFactory.getLogger(GCPAuthenticator.class); |
45 | 53 |
|
46 | 54 | private final ProcessBuilder pb; |
| 55 | + private GoogleCredentials gc; |
47 | 56 |
|
48 | 57 | public GCPAuthenticator() { |
49 | | - this(new ProcessBuilder()); |
| 58 | + this(new ProcessBuilder(), null); |
50 | 59 | } |
51 | 60 |
|
52 | | - public GCPAuthenticator(ProcessBuilder pb) { |
| 61 | + public GCPAuthenticator(ProcessBuilder pb, GoogleCredentials gc) { |
53 | 62 | this.pb = pb; |
| 63 | + this.gc = gc; |
54 | 64 | } |
55 | 65 |
|
56 | 66 | @Override |
@@ -81,8 +91,39 @@ public boolean isExpired(Map<String, Object> config) { |
81 | 91 |
|
82 | 92 | @Override |
83 | 93 | public Map<String, Object> refresh(Map<String, Object> config) { |
84 | | - if (!config.containsKey(CMD_ARGS) || !config.containsKey(CMD_PATH)) |
85 | | - throw new RuntimeException("Could not refresh token"); |
| 94 | + if (isCmd(config)) { |
| 95 | + return refreshCmd(config); |
| 96 | + } |
| 97 | + // Google Application Credentials-based refresh |
| 98 | + // https://cloud.google.com/kubernetes-engine/docs/how-to/api-server-authentication#environments-without-gcloud |
| 99 | + String[] scopes = parseScopes(config); |
| 100 | + try { |
| 101 | + if (this.gc == null) this.gc = GoogleCredentials.getApplicationDefault().createScoped(scopes); |
| 102 | + AccessToken accessToken = gc.getAccessToken(); |
| 103 | + config.put(ACCESS_TOKEN, accessToken.getTokenValue()); |
| 104 | + config.put(EXPIRY, accessToken.getExpirationTime()); |
| 105 | + return config; |
| 106 | + } catch (IOException e) { |
| 107 | + throw new RuntimeException("The Application Default Credentials are not available.", e); |
| 108 | + } |
| 109 | + } |
| 110 | + |
| 111 | + public String[] parseScopes(Map<String, Object> config) { |
| 112 | + String scopes = (String) config.get(SCOPES); |
| 113 | + if (scopes == null) { |
| 114 | + return DEFAULT_SCOPES; |
| 115 | + } |
| 116 | + if (scopes.isEmpty()) { |
| 117 | + return new String[] {}; |
| 118 | + } |
| 119 | + return scopes.split(","); |
| 120 | + } |
| 121 | + |
| 122 | + private boolean isCmd(Map<String, Object> config) { |
| 123 | + return config.containsKey(CMD_ARGS) && config.containsKey(CMD_PATH); |
| 124 | + } |
| 125 | + |
| 126 | + private Map<String, Object> refreshCmd(Map<String, Object> config) { |
86 | 127 | String cmdPath = (String) config.get(CMD_PATH); |
87 | 128 | String cmdArgs = (String) config.get(CMD_ARGS); |
88 | 129 | List<String> fullCmd = |
|
0 commit comments