Tries to obtain URI of the V2 authorization service based on the "realm", "scope" and "service" auth params from the initial "401 unauthorized" response of the Docker V2 registry (see details in https://docs.docker.com/registry/spec/auth/token). If any of the params are missing from the "WWW-Authenticate" header, this function falls back to the scheme implemented in Docker image puller (see MESOS
| 1145 | // repository scope on its own. Scope grammar and semantics are documented in |
| 1146 | // https://docs.docker.com/registry/spec/auth/scope . |
| 1147 | Future<string> DockerFetcherPluginProcess::getAuthServiceUri( |
| 1148 | const string& repository, |
| 1149 | const URI& initialUri, |
| 1150 | const http::Response& initialResponse, |
| 1151 | const http::Headers& basicAuthHeaders) const |
| 1152 | { |
| 1153 | const Try<hashmap<string, string>> authParam = |
| 1154 | getBearerAuthParam(initialUri, initialResponse); |
| 1155 | |
| 1156 | if (authParam.isError()) { |
| 1157 | LOG(WARNING) << authParam.error(); |
| 1158 | return Failure(authParam.error()); |
| 1159 | } |
| 1160 | |
| 1161 | // `authParam` is supposed to contain the 'realm', 'service' |
| 1162 | // and 'scope' information for bearer authentication. |
| 1163 | if (authParam->contains("realm") && |
| 1164 | authParam->contains("service") && |
| 1165 | authParam->contains("scope")) { |
| 1166 | // TODO(jieyu): Currently, we don't expect the auth server to return |
| 1167 | // a service or a scope that needs encoding. |
| 1168 | return authParam->at("realm") + "?" + |
| 1169 | "service=" + authParam->at("service") + "&" + |
| 1170 | "scope=" + authParam->at("scope"); |
| 1171 | } |
| 1172 | |
| 1173 | const string msg = |
| 1174 | "Missing 'realm', 'service' or 'scope' in header WWW-Authenticate: " + |
| 1175 | initialResponse.headers.at("WWW-Authenticate"); |
| 1176 | |
| 1177 | if (!enableAuthServiceUriFallback) { |
| 1178 | return Failure(msg); |
| 1179 | } |
| 1180 | |
| 1181 | LOG(WARNING) << msg; |
| 1182 | |
| 1183 | const URI registryRootUri = getRegistryRootUri(initialUri); |
| 1184 | return curl(registryRootUri, basicAuthHeaders, stallTimeout) |
| 1185 | .then([repository, registryRootUri](const http::Response& rootResponse) |
| 1186 | -> Future<string> { |
| 1187 | const Try<hashmap<string, string>> authParam = |
| 1188 | getBearerAuthParam(registryRootUri, rootResponse); |
| 1189 | |
| 1190 | if (authParam.isError()) { |
| 1191 | LOG(WARNING) << authParam.error(); |
| 1192 | return Failure(authParam.error()); |
| 1193 | } |
| 1194 | |
| 1195 | if (!authParam->contains("realm")) { |
| 1196 | return Failure( |
| 1197 | "Missing 'realm' in WWW-Authenticate header obtained from " + |
| 1198 | stringify(registryRootUri)); |
| 1199 | } |
| 1200 | |
| 1201 | return authParam->at("realm") + "?scope=repository:" + repository + |
| 1202 | ":pull"; |
| 1203 | }); |
| 1204 | } |
nothing calls this directly
no test coverage detected