Skip to content
This repository has been archived by the owner on Nov 13, 2019. It is now read-only.

Commit

Permalink
allow downloading and deletion of protected rpms for authenticated users
Browse files Browse the repository at this point in the history
  • Loading branch information
heroldus committed May 21, 2015
1 parent 126bc14 commit aeae89e
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

Expand Down Expand Up @@ -51,35 +52,52 @@ public boolean isAllowedPropagationRepo(String repo) {
}

public boolean isAllowed(FileDescriptor fileDescriptor, Authentication authentication) {
boolean isWebCall = false;
HostName remoteHostName = null;
if ((authentication != null) && (authentication.getDetails() instanceof AuthenticationDetails)) {
AuthenticationDetails authenticationDetails = (AuthenticationDetails) (authentication.getDetails());
isWebCall = authenticationDetails.isWebRequest();
remoteHostName = authenticationDetails.getRemoteHost();
} else {
logUnknownAuthentication(authentication);
if (isAuthenticatedUser(authentication)) {
LOGGER.debug("...allowed because authenticated user.");
return true;
}

if (isNotAllowedForWebCallOnProtectedRepo(fileDescriptor, isWebCall, remoteHostName)) {
return false;
if (isBackendCall(authentication)) {
LOGGER.debug("...allowed because backend call.");
return true;
}

if (isNotCallOnProtectedRepo(fileDescriptor)) {
LOGGER.debug("...allowed because unprotected repo.");
return true;
}
LOGGER.debug("...allowed.");

HostName remoteHost = ((AuthenticationDetails) (authentication.getDetails())).getRemoteHost();
if (isAllowedWebCallOnProtectedRepo(fileDescriptor, remoteHost)) {
LOGGER.debug("...allowed because authorized call to protected repo.");
return true;
}

return false;
}

public boolean isBackendCall(Authentication authentication) {
if (hasAuthenticationDetails(authentication)) {
return !((AuthenticationDetails) (authentication.getDetails())).isWebRequest();
}

logUnknownAuthentication(authentication);
return true;
}

public boolean isNotAllowedForWebCallOnProtectedRepo(FileDescriptor fileDescriptor, boolean isWebCall, HostName remoteHostName) {
return isWebCallOnProtectedRepo(fileDescriptor, isWebCall) &&
!isAllowedForWebCallOnProtectedRepo(fileDescriptor, remoteHostName);
private boolean isAuthenticatedUser(Authentication authentication) {
return authentication != null && authentication instanceof UsernamePasswordAuthenticationToken;
}

private static boolean hasAuthenticationDetails(Authentication authentication) {
return (authentication != null) && (authentication.getDetails() instanceof AuthenticationDetails);
}

private boolean isWebCallOnProtectedRepo(FileDescriptor fileDescriptor, boolean isWebCall) {
return isWebCall && !fileDescriptor.getArch().equals("repodata") &&
protectedRepos.contains(fileDescriptor.getRepo());
private boolean isNotCallOnProtectedRepo(FileDescriptor fileDescriptor) {
return fileDescriptor.getArch().equals("repodata") || !protectedRepos.contains(fileDescriptor.getRepo());
}

public boolean isAllowedForWebCallOnProtectedRepo(FileDescriptor fileDescriptor, HostName remoteHostName) {
public boolean isAllowedWebCallOnProtectedRepo(FileDescriptor fileDescriptor, HostName remoteHostName) {
LOGGER.info("check access permission for {} to {}", remoteHostName, fileDescriptor.getPath());
if (remoteHostName.isIp()) {
LOGGER.debug("..is IP...");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import org.junit.Before;
import org.junit.Test;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.context.request.RequestContextHolder;

import static de.is24.infrastructure.gridfs.http.security.UserAuthorities.USER_AUTHORITIES;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.springframework.security.core.authority.AuthorityUtils.createAuthorityList;
Expand Down Expand Up @@ -115,6 +117,18 @@ public void allowAccessToFilesForInternalCallsInProtectedRepos() throws Exceptio
assertThat(allowed, is(true));
}

@Test
public void allowAccessToProtectedRepoRPMsForAuthenticatedUsers() throws Exception {
boolean allowed = patternEvaluator.isAllowed(PROTECTED_NOARCH_RPM_FOR_DEVXYZ01_DESCRIPTOR, authticatedUser());
assertThat(allowed, is(true));
}

private Authentication authticatedUser() {
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("username", "password", USER_AUTHORITIES);
authentication.setDetails(new AuthenticationDetails(new HostName("localhost")));
return authentication;
}


private Authentication currentAuthentication(String hostname) {
AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken("key", "anonymousUser", createAuthorityList("ROLE_ANONYMOUS"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import de.is24.infrastructure.gridfs.http.web.boot.AbstractContainerAndMongoDBStarter;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
Expand All @@ -19,14 +22,17 @@
import java.security.NoSuchAlgorithmException;

import static de.is24.infrastructure.gridfs.http.web.RepoTestUtils.uploadRpm;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.apache.commons.lang.StringUtils.substringBefore;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;


public class SecurityIT extends AbstractContainerAndMongoDBStarter {
public static final String RANDOM_STRING = "foobar";
public static final String DOMAIN_SEPERATOR = ".";
private String repoUrl;
private String myProtectedRPM;
private String anotherHostsProtectedRPM;
Expand Down Expand Up @@ -54,11 +60,28 @@ public void allowDownloadOfMyProtectedRPM() throws Exception {
}

@Test
public void denyDownloadOfOtherHostsProtectedRPM() throws Exception {
public void denyUnauthenticaedDownloadOfProtectedRPM() throws Exception {
HttpGet get = new HttpGet(repoUrl + "/noarch/" + anotherHostsProtectedRPM);

HttpClient httpClientWithoutAuthentication = HttpClientBuilder.create().build();
HttpResponse response = httpClientWithoutAuthentication.execute(get);
assertThat(response.getStatusLine().getStatusCode(), is(SC_UNAUTHORIZED));
}

@Test
public void allowDownloadOfProtectedRPMForAuthenticatedUser() throws Exception {
HttpGet get = new HttpGet(repoUrl + "/noarch/" + anotherHostsProtectedRPM);

HttpResponse response = httpClient.execute(get);
assertThat(response.getStatusLine().getStatusCode(), is(SC_FORBIDDEN));
assertThat(response.getStatusLine().getStatusCode(), is(SC_OK));
}

@Test
public void allowDeletionOfProtectedRPMToAuthenticatedUsers() throws Exception {
HttpDelete delete = new HttpDelete(repoUrl + "/noarch/" + anotherHostsProtectedRPM);

HttpResponse response = httpClient.execute(delete);
assertThat(response.getStatusLine().getStatusCode(), is(SC_NO_CONTENT));
}

private String getMyShortHostName() throws UnknownHostException {
Expand All @@ -70,12 +93,7 @@ private String getMyShortHostName() throws UnknownHostException {
} else {
myHostName = InetAddress.getLocalHost().getHostName();
}

int dotIndex = myHostName.indexOf(".");
if (dotIndex >= 0) {
myHostName = myHostName.substring(0, dotIndex);
}
return myHostName;
return substringBefore(myHostName, DOMAIN_SEPERATOR);
}

private String buildProtectedRPMForMyHostName() throws IOException, NoSuchAlgorithmException {
Expand Down

0 comments on commit aeae89e

Please sign in to comment.