Skip to content

Commit

Permalink
Improve token scopes validation in OciRegistryApi
Browse files Browse the repository at this point in the history
  • Loading branch information
SgtSilvio committed Feb 2, 2025
1 parent b645853 commit 6832cdd
Showing 1 changed file with 9 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -549,19 +549,19 @@ internal class OciRegistryApi(httpClient: HttpClient) {
private fun tryAuthorize(
responseHeaders: HttpHeaders,
registryUrl: URI,
scopes: Set<OciRegistryResourceScope>,
requiredScopes: Set<OciRegistryResourceScope>,
credentials: Credentials?,
): Mono<String>? {
val bearerParams = decodeBearerParams(responseHeaders) ?: return null // TODO return parsing error
val realm = bearerParams["realm"] ?: throw IllegalArgumentException("bearer authorization header is missing 'realm'")
val service = bearerParams["service"] ?: throw IllegalArgumentException("bearer authorization header is missing 'service'")
val scope = bearerParams["scope"] ?: throw IllegalArgumentException("bearer authorization header is missing 'scope'")
val scopesFromResponse = scope.split(' ').mapTo(HashSet()) { it.decodeToResourceScope() }
val scopes = scope.split(' ').mapTo(HashSet()) { it.decodeToResourceScope() }
// if (scopesFromResponse != scopes) { // TODO GitHub container registry always returns pull as action (no pull,push) and returns "user/image" as repository when sending basic auth in first request, log a warning instead?
// throw IllegalStateException("scopes do not match, required: $scopes, from bearer authorization header: $scopesFromResponse")
// }
return tokenCache.getMono(TokenCacheKey(registryUrl, scopesFromResponse, credentials?.hashed())) { key ->
val scopeParams = scopesFromResponse.joinToString("&scope=", "scope=") { it.encodeToString() }
return tokenCache.getMono(TokenCacheKey(registryUrl, scopes, credentials?.hashed())) { key ->
val scopeParams = key.scopes.joinToString("&scope=", "scope=") { it.encodeToString() }
httpClient.headers { headers ->
if (credentials != null) {
headers[HttpHeaderNames.AUTHORIZATION] = credentials.encodeBasicAuthorization()
Expand All @@ -577,14 +577,16 @@ internal class OciRegistryApi(httpClient: HttpClient) {
}
val registryToken = OciRegistryToken(token)
val grantedScopes = registryToken.claims?.scopes
if ((grantedScopes != null) && (grantedScopes != key.scopes)) {
if (grantedScopes.isNotEmpty()) {
if (grantedScopes != null) {
if ((grantedScopes != key.scopes) && grantedScopes.isNotEmpty()) {
tokenCache.asMap().putIfAbsent(
key.copy(scopes = grantedScopes),
CompletableFuture.completedFuture(registryToken),
)
}
throw InsufficientScopesException(key.scopes, grantedScopes)
if (grantedScopes != requiredScopes) {
throw InsufficientScopesException(requiredScopes, grantedScopes)
}
}
registryToken
}
Expand Down

0 comments on commit 6832cdd

Please sign in to comment.