Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add auth integration tests #892

Merged
merged 13 commits into from
Jul 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: integration tests

on: [push, pull_request]

jobs:
maven-integration-test:
runs-on: ubuntu-latest
name: Maven Integration Test
name: integration-test-java
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
Expand Down
20 changes: 20 additions & 0 deletions auth/.openapi-generator-ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
settings.gradle
README.md
pom.xml
gradle
git_push.sh
build.sbt
build.gradle
.travis*
.gitignore
src/main/resources/api.yaml
gradle*
gradle/*
gradle-wrapper.*
gradle**
gradle/
src/main/java/feast/auth/providers/http/HttpAuthorizationProvider.java
src/main/java/feast/auth/providers/http/ketoadaptor/api/CheckAccessApiController.java
src/main/java/feast/auth/providers/http/ketoadaptor/api/KetoAuth.java
src/main/AndroidManifest.xml
.openapi-generator/
76 changes: 66 additions & 10 deletions auth/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@
<name>Feast Authentication and Authorization</name>

<properties>
<external.auth.client.package.name>feast.auth.generated.client</external.auth.client.package.name>
<feast.auth.providers.http.client.package.name>feast.auth.providers.http.client
</feast.auth.providers.http.client.package.name>
<gson-fire-version>1.8.4</gson-fire-version>
<swagger-core-version>1.5.24</swagger-core-version>
<okhttp-version>3.14.7</okhttp-version>
<gson-version>2.8.6</gson-version>
<commons-lang3-version>3.10</commons-lang3-version>
<javax-annotation-version>1.3.2</javax-annotation-version>
<junit-version>4.13</junit-version>
<springfox-version>2.8.0</springfox-version>
</properties>
<dependencies>
<dependency>
Expand Down Expand Up @@ -60,10 +62,6 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
Expand Down Expand Up @@ -106,6 +104,55 @@
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.1.0</version>
</dependency>
<!-- Bean Validation API support -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
Expand All @@ -115,16 +162,17 @@
<version>4.3.1</version>
<executions>
<execution>
<id>client</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/api.yaml</inputSpec>
<generatorName>java</generatorName>
<packageName>${external.auth.client.package.name}</packageName>
<modelPackage>${external.auth.client.package.name}.model</modelPackage>
<apiPackage>${external.auth.client.package.name}.api</apiPackage>
<invokerPackage>${external.auth.client.package.name}.invoker</invokerPackage>
<packageName>${feast.auth.providers.http.client.package.name}</packageName>
<modelPackage>${feast.auth.providers.http.client.package.name}.model</modelPackage>
<apiPackage>${feast.auth.providers.http.client.package.name}.api</apiPackage>
<invokerPackage>${feast.auth.providers.http.client.package.name}.invoker</invokerPackage>
<configOptions>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
Expand All @@ -143,7 +191,15 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<excludePackageNames>feast.auth.generated.client.api</excludePackageNames>
<excludePackageNames>feast.auth.providers.http.client.*</excludePackageNames>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<argLine>-Xms2048m -Xmx2048m -Djdk.net.URLClassPath.disableClassPathURLCheck=true</argLine>
</configuration>
</plugin>
<plugin>
Expand Down
2 changes: 1 addition & 1 deletion auth/src/main/java/feast/auth/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import feast.auth.authentication.DefaultJwtAuthenticationProvider;
import feast.auth.authorization.AuthorizationProvider;
import feast.auth.authorization.HttpAuthorizationProvider;
import feast.auth.providers.http.HttpAuthorizationProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package feast.auth.authorization;
package feast.auth.providers.http;

import feast.auth.authorization.AuthorizationProvider;
import feast.auth.authorization.AuthorizationResult;
import feast.auth.config.CacheConfiguration;
import feast.auth.generated.client.api.DefaultApi;
import feast.auth.generated.client.invoker.ApiClient;
import feast.auth.generated.client.invoker.ApiException;
import feast.auth.generated.client.model.CheckAccessRequest;
import feast.auth.providers.http.client.api.DefaultApi;
import feast.auth.providers.http.client.invoker.ApiClient;
import feast.auth.providers.http.client.invoker.ApiException;
import feast.auth.providers.http.client.model.CheckAccessRequest;
import feast.auth.utils.AuthUtils;
import java.util.Map;
import org.slf4j.Logger;
Expand Down Expand Up @@ -86,7 +88,7 @@ public AuthorizationResult checkAccessToProject(String projectId, Authentication
try {
Jwt credentials = ((Jwt) authentication.getCredentials());
// Make authorization request to external service
feast.auth.generated.client.model.AuthorizationResult authResult =
feast.auth.providers.http.client.model.AuthorizationResult authResult =
this.defaultApiClient.checkAccessPost(
checkAccessRequest, "Bearer " + credentials.getTokenValue());
if (authResult == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@
import feast.auth.config.SecurityProperties;
import feast.auth.config.SecurityProperties.AuthenticationProperties;
import feast.auth.config.SecurityProperties.AuthorizationProperties;
import feast.auth.generated.client.api.DefaultApi;
import feast.auth.generated.client.model.AuthorizationResult;
import feast.auth.generated.client.model.CheckAccessRequest;
import feast.auth.providers.http.HttpAuthorizationProvider;
import feast.auth.providers.http.client.api.DefaultApi;
import feast.auth.providers.http.client.model.AuthorizationResult;
import feast.auth.providers.http.client.model.CheckAccessRequest;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
Expand Down
31 changes: 24 additions & 7 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
<artifactId>flyway-maven-plugin</artifactId>
<version>${flyway.version}</version>
</plugin>

</plugins>
</build>

Expand Down Expand Up @@ -315,12 +314,18 @@
<version>5.2.5.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
woop marked this conversation as resolved.
Show resolved Hide resolved
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
Expand All @@ -333,6 +338,12 @@
<version>1.14.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>sh.ory.keto</groupId>
<artifactId>keto-client</artifactId>
<version>0.4.4-alpha.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
Expand All @@ -345,6 +356,12 @@
<version>1.14.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.27.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

@Configuration
@Slf4j
@ComponentScan("feast.auth")
@ComponentScan("feast.auth.config")
public class CoreSecurityConfig {

/**
Expand Down
14 changes: 11 additions & 3 deletions core/src/main/java/feast/core/grpc/CoreServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.context.SecurityContextHolder;

/** Implementation of the feast core GRPC service. */
Expand Down Expand Up @@ -178,10 +179,10 @@ public void listStores(
public void applyFeatureSet(
ApplyFeatureSetRequest request, StreamObserver<ApplyFeatureSetResponse> responseObserver) {

accessManagementService.checkIfProjectMember(
SecurityContextHolder.getContext(), request.getFeatureSet().getSpec().getProject());

String projectId = null;
try {
projectId = request.getFeatureSet().getSpec().getProject();
accessManagementService.checkIfProjectMember(SecurityContextHolder.getContext(), projectId);
ApplyFeatureSetResponse response = specService.applyFeatureSet(request.getFeatureSet());
responseObserver.onNext(response);
responseObserver.onCompleted();
Expand All @@ -192,6 +193,13 @@ public void applyFeatureSet(
e);
responseObserver.onError(
Status.ALREADY_EXISTS.withDescription(e.getMessage()).withCause(e).asRuntimeException());
} catch (AccessDeniedException e) {
log.info(String.format("User prevented from accessing project: %s", projectId));
responseObserver.onError(
Status.PERMISSION_DENIED
.withDescription(e.getMessage())
.withCause(e)
.asRuntimeException());
} catch (Exception e) {
log.error("Exception has occurred in ApplyFeatureSet method: ", e);
responseObserver.onError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public void checkIfProjectMember(SecurityContext securityContext, String project
AuthorizationResult result =
this.authorizationProvider.checkAccessToProject(projectId, authentication);
if (!result.isAllowed()) {
throw new AccessDeniedException(result.getFailureReason().orElse("AccessDenied"));
throw new AccessDeniedException(result.getFailureReason().orElse("Access Denied"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package feast.core.grpc;
package feast.core.auth;

import static org.junit.Assert.assertThrows;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
Expand All @@ -29,6 +29,7 @@
import feast.auth.config.SecurityProperties;
import feast.core.config.FeastProperties;
import feast.core.dao.ProjectRepository;
import feast.core.grpc.CoreServiceImpl;
import feast.core.model.Entity;
import feast.core.model.Feature;
import feast.core.model.FeatureSet;
Expand All @@ -53,7 +54,6 @@
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
Expand Down Expand Up @@ -107,8 +107,8 @@ public void shouldNotApplyFeatureSetIfNotProjectMember() throws InvalidProtocolB
ApplyFeatureSetRequest request =
ApplyFeatureSetRequest.newBuilder().setFeatureSet(spec).build();

assertThrows(
AccessDeniedException.class, () -> coreService.applyFeatureSet(request, responseObserver));
coreService.applyFeatureSet(request, responseObserver);
assertEquals("PERMISSION_DENIED: Access Denied", responseObserver.getError().getMessage());
}

@Test
Expand Down
Loading