Commit b09f782a authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Denied tar/zip generation to anonymous users

parent 993b2a92
Loading
Loading
Loading
Loading
Loading
+13 −6
Original line number Original line Diff line number Diff line
@@ -6,12 +6,12 @@
package it.inaf.ia2.transfer.controller;
package it.inaf.ia2.transfer.controller;


import it.inaf.ia2.transfer.auth.TokenPrincipal;
import it.inaf.ia2.transfer.auth.TokenPrincipal;
import it.inaf.ia2.transfer.exception.PermissionDeniedException;
import it.inaf.ia2.transfer.service.ArchiveJob;
import it.inaf.ia2.transfer.service.ArchiveJob;
import it.inaf.ia2.transfer.service.ArchiveJob.Type;
import it.inaf.ia2.transfer.service.ArchiveJob.Type;
import it.inaf.ia2.transfer.service.ArchiveService;
import it.inaf.ia2.transfer.service.ArchiveService;
import java.io.File;
import java.io.File;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletableFuture;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpHeaders;
@@ -30,9 +30,6 @@ public class ArchiveFileController extends FileController {
    @Autowired
    @Autowired
    private ArchiveService archiveService;
    private ArchiveService archiveService;


    @Autowired
    private HttpServletRequest request;

    @Autowired
    @Autowired
    private HttpServletResponse response;
    private HttpServletResponse response;


@@ -42,7 +39,7 @@ public class ArchiveFileController extends FileController {
        Type type = Type.valueOf(archiveRequest.getType());
        Type type = Type.valueOf(archiveRequest.getType());


        ArchiveJob job = new ArchiveJob();
        ArchiveJob job = new ArchiveJob();
        job.setPrincipal((TokenPrincipal) request.getUserPrincipal());
        job.setPrincipal(getPrincipal());
        job.setJobId(archiveRequest.getJobId());
        job.setJobId(archiveRequest.getJobId());
        job.setType(type);
        job.setType(type);
        job.setVosPaths(archiveRequest.getPaths());
        job.setVosPaths(archiveRequest.getPaths());
@@ -59,10 +56,20 @@ public class ArchiveFileController extends FileController {
    @GetMapping(value = "/archive/{fileName}")
    @GetMapping(value = "/archive/{fileName}")
    public void getArchiveFile(@PathVariable("fileName") String fileName) {
    public void getArchiveFile(@PathVariable("fileName") String fileName) {


        TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal();
        TokenPrincipal principal = getPrincipal();


        File file = archiveService.getArchiveParentDir(principal).toPath().resolve(fileName).toFile();
        File file = archiveService.getArchiveParentDir(principal).toPath().resolve(fileName).toFile();


        FileResponseUtil.getFileResponse(response, file);
        FileResponseUtil.getFileResponse(response, file);
    }
    }

    private TokenPrincipal getPrincipal() {
        TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal();

        if ("anonymous".equals(principal.getName())) {
            throw new PermissionDeniedException("Tar/Zip archive generation not allowed to anonymous users");
        }
        
        return principal;
    }
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -65,7 +65,7 @@ public class GetFileController extends FileController {
                FileInfo fileInfo = optFileInfo.get();
                FileInfo fileInfo = optFileInfo.get();


                if (!authorizationService.isDownloadable(fileInfo, (TokenPrincipal) request.getUserPrincipal())) {
                if (!authorizationService.isDownloadable(fileInfo, (TokenPrincipal) request.getUserPrincipal())) {
                    throw new PermissionDeniedException(path);
                    throw new PermissionDeniedException("PermissionDenied Path: " + path);
                }
                }


                File file = new File(fileInfo.getOsPath());
                File file = new File(fileInfo.getOsPath());
+2 −2
Original line number Original line Diff line number Diff line
@@ -11,8 +11,8 @@ import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.FORBIDDEN)
@ResponseStatus(value = HttpStatus.FORBIDDEN)
public class PermissionDeniedException extends JobException {
public class PermissionDeniedException extends JobException {


    public PermissionDeniedException(String path) {
    public PermissionDeniedException(String errorDetail) {
        super(Type.FATAL, "Permission Denied");
        super(Type.FATAL, "Permission Denied");
        setErrorDetail("PermissionDenied Path: " + path);
        setErrorDetail(errorDetail);
    }
    }
}
}
+62 −2
Original line number Original line Diff line number Diff line
@@ -6,26 +6,34 @@
package it.inaf.ia2.transfer.controller;
package it.inaf.ia2.transfer.controller;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import it.inaf.ia2.transfer.auth.TokenPrincipal;
import it.inaf.ia2.transfer.service.ArchiveJob;
import it.inaf.ia2.transfer.service.ArchiveJob;
import it.inaf.ia2.transfer.service.ArchiveService;
import it.inaf.ia2.transfer.service.ArchiveService;
import java.io.File;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Test;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.util.FileSystemUtils;


@SpringBootTest
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureMockMvc(addFilters = false)
public class ArchiveFileControllerTest {
public class ArchiveFileControllerTest {


    private static final ObjectMapper MAPPER = new ObjectMapper();
    private static final ObjectMapper MAPPER = new ObjectMapper();
@@ -45,6 +53,7 @@ public class ArchiveFileControllerTest {
        request.setPaths(Arrays.asList("/path/to/file1", "/path/to/file2"));
        request.setPaths(Arrays.asList("/path/to/file1", "/path/to/file2"));


        mockMvc.perform(post("/archive")
        mockMvc.perform(post("/archive")
                .principal(fakePrincipal("user1"))
                .contentType(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON)
                .content(MAPPER.writeValueAsString(request)))
                .content(MAPPER.writeValueAsString(request)))
                .andDo(print())
                .andDo(print())
@@ -53,9 +62,60 @@ public class ArchiveFileControllerTest {
        verify(archiveService, times(1)).createArchive(argThat(job -> {
        verify(archiveService, times(1)).createArchive(argThat(job -> {
            assertEquals("123", job.getJobId());
            assertEquals("123", job.getJobId());
            assertEquals(ArchiveJob.Type.TAR, job.getType());
            assertEquals(ArchiveJob.Type.TAR, job.getType());
            assertEquals("anonymous", job.getPrincipal().getName());
            assertEquals("user1", job.getPrincipal().getName());
            assertEquals(2, job.getVosPaths().size());
            assertEquals(2, job.getVosPaths().size());
            return true;
            return true;
        }));
        }));
    }
    }

    @Test
    public void testGetArchive() throws Exception {

        File tmpDir = Files.createTempDirectory("tmp").toFile();

        try {
            tmpDir.toPath().resolve("123.zip").toFile().createNewFile();

            when(archiveService.getArchiveParentDir(any())).thenReturn(tmpDir);

            mockMvc.perform(get("/archive/123.zip")
                    .principal(fakePrincipal("user1")))
                    .andDo(print())
                    .andExpect(status().isOk());

        } finally {
            FileSystemUtils.deleteRecursively(tmpDir);
        }
    }

    @Test
    public void testAnonymousCantCreateArchive() throws Exception {

        ArchiveRequest request = new ArchiveRequest();
        request.setJobId("123");
        request.setType("ZIP");
        request.setPaths(Arrays.asList("/ignore"));

        mockMvc.perform(post("/archive")
                .principal(fakePrincipal("anonymous"))
                .contentType(MediaType.APPLICATION_JSON)
                .content(MAPPER.writeValueAsString(request)))
                .andDo(print())
                .andExpect(status().isForbidden());
    }

    @Test
    public void testAnonymousCantGetArchive() throws Exception {

        mockMvc.perform(get("/archive/123.zip")
                .principal(fakePrincipal("anonymous")))
                .andDo(print())
                .andExpect(status().isForbidden());
    }

    private TokenPrincipal fakePrincipal(String name) {
        TokenPrincipal principal = mock(TokenPrincipal.class);
        when(principal.getName()).thenReturn(name);
        return principal;
    }
}
}