AllowAllDockerProtocolMapper now allows multiple resourceScopes delimited by spaces as specified by the docker auth token spec.

Closes #17187
This commit is contained in:
tomjo 2023-02-22 19:48:25 +01:00 committed by Marek Posolda
parent 53ff6c98b4
commit 705d20d4a2
4 changed files with 294 additions and 4 deletions

View file

@ -41,10 +41,12 @@ public class AllowAllDockerProtocolMapper extends DockerAuthV2ProtocolMapper imp
responseToken.getAccessItems().clear();
final String requestedScope = clientSession.getNote(DockerAuthV2Protocol.SCOPE_PARAM);
if (requestedScope != null) {
final DockerAccess allRequestedAccess = new DockerAccess(requestedScope);
responseToken.getAccessItems().add(allRequestedAccess);
final String requestedScopes = clientSession.getNote(DockerAuthV2Protocol.SCOPE_PARAM);
if (requestedScopes != null) {
for (String requestedScope : requestedScopes.split(" ")) {
final DockerAccess requestedAccess = new DockerAccess(requestedScope);
responseToken.getAccessItems().add(requestedAccess);
}
}
return responseToken;

View file

@ -0,0 +1,119 @@
package org.keycloak.protocol;
import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import java.util.HashMap;
import java.util.Map;
public class TestAuthenticatedClientSessionModel implements AuthenticatedClientSessionModel {
private final Map<String, String> notes = new HashMap<>();
@Override
public String getId() {
return null;
}
@Override
public int getTimestamp() {
return 0;
}
@Override
public void setTimestamp(int timestamp) {
}
@Override
public void detachFromUserSession() {
}
@Override
public UserSessionModel getUserSession() {
return null;
}
@Override
public String getCurrentRefreshToken() {
return null;
}
@Override
public void setCurrentRefreshToken(String currentRefreshToken) {
}
@Override
public int getCurrentRefreshTokenUseCount() {
return 0;
}
@Override
public void setCurrentRefreshTokenUseCount(int currentRefreshTokenUseCount) {
}
@Override
public String getNote(String name) {
return notes.get(name);
}
@Override
public void setNote(String name, String value) {
notes.put(name, value);
}
@Override
public void removeNote(String name) {
notes.remove(name);
}
@Override
public Map<String, String> getNotes() {
return notes;
}
@Override
public String getRedirectUri() {
return null;
}
@Override
public void setRedirectUri(String uri) {
}
@Override
public RealmModel getRealm() {
return null;
}
@Override
public ClientModel getClient() {
return null;
}
@Override
public String getAction() {
return null;
}
@Override
public void setAction(String action) {
}
@Override
public String getProtocol() {
return null;
}
@Override
public void setProtocol(String method) {
}
}

View file

@ -0,0 +1,50 @@
package org.keycloak.protocol.docker.mapper;
import org.junit.Test;
import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.protocol.TestAuthenticatedClientSessionModel;
import org.keycloak.protocol.docker.DockerAuthV2Protocol;
import org.keycloak.representations.docker.DockerAccess;
import org.keycloak.representations.docker.DockerResponseToken;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
public class AllowAllDockerProtocolMapperTest {
@Test
public void transformsResourceScope() {
DockerResponseToken dockerResponseToken = new DockerResponseToken();
AuthenticatedClientSessionModel authenticatedClientSessionModel = new TestAuthenticatedClientSessionModel();
authenticatedClientSessionModel.setNote(DockerAuthV2Protocol.SCOPE_PARAM, "repository:my-image:pull,push");
DockerResponseToken result = new AllowAllDockerProtocolMapper().transformDockerResponseToken(dockerResponseToken, new ProtocolMapperModel(), null, null, authenticatedClientSessionModel);
assertThat(result.getAccessItems(), containsInAnyOrder(new DockerAccess("repository:my-image:pull,push")));
}
@Test
public void transformsResourceScopeNull() {
DockerResponseToken dockerResponseToken = new DockerResponseToken();
AuthenticatedClientSessionModel authenticatedClientSessionModel = new TestAuthenticatedClientSessionModel();
authenticatedClientSessionModel.setNote(DockerAuthV2Protocol.SCOPE_PARAM, null);
DockerResponseToken result = new AllowAllDockerProtocolMapper().transformDockerResponseToken(dockerResponseToken, new ProtocolMapperModel(), null, null, authenticatedClientSessionModel);
assertThat(result.getAccessItems(), containsInAnyOrder());
}
@Test
public void transformsMultipleResourceScopes() {
DockerResponseToken dockerResponseToken = new DockerResponseToken();
AuthenticatedClientSessionModel authenticatedClientSessionModel = new TestAuthenticatedClientSessionModel();
authenticatedClientSessionModel.setNote(DockerAuthV2Protocol.SCOPE_PARAM, "repository:my-image:pull,push repository:my-base-image:pull");
DockerResponseToken result = new AllowAllDockerProtocolMapper().transformDockerResponseToken(dockerResponseToken, new ProtocolMapperModel(), null, null, authenticatedClientSessionModel);
assertThat(result.getAccessItems(), containsInAnyOrder(new DockerAccess("repository:my-image:pull,push"), new DockerAccess("repository:my-base-image:pull")));
}
}

View file

@ -0,0 +1,119 @@
package org.keycloak.protocol.docker.mapper;
import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import java.util.HashMap;
import java.util.Map;
class TestAuthenticatedClientSessionModel implements AuthenticatedClientSessionModel {
private final Map<String, String> notes = new HashMap<>();
@Override
public String getId() {
return null;
}
@Override
public int getTimestamp() {
return 0;
}
@Override
public void setTimestamp(int timestamp) {
}
@Override
public void detachFromUserSession() {
}
@Override
public UserSessionModel getUserSession() {
return null;
}
@Override
public String getCurrentRefreshToken() {
return null;
}
@Override
public void setCurrentRefreshToken(String currentRefreshToken) {
}
@Override
public int getCurrentRefreshTokenUseCount() {
return 0;
}
@Override
public void setCurrentRefreshTokenUseCount(int currentRefreshTokenUseCount) {
}
@Override
public String getNote(String name) {
return notes.get(name);
}
@Override
public void setNote(String name, String value) {
notes.put(name, value);
}
@Override
public void removeNote(String name) {
notes.remove(name);
}
@Override
public Map<String, String> getNotes() {
return notes;
}
@Override
public String getRedirectUri() {
return null;
}
@Override
public void setRedirectUri(String uri) {
}
@Override
public RealmModel getRealm() {
return null;
}
@Override
public ClientModel getClient() {
return null;
}
@Override
public String getAction() {
return null;
}
@Override
public void setAction(String action) {
}
@Override
public String getProtocol() {
return null;
}
@Override
public void setProtocol(String method) {
}
}