Skip to content

Commit 72cc120

Browse files
authored
Add auth integration tests (#892)
* Add auth integration tests * Change integration test name * Skip JavaDoc for External Auth HTTP Client * Update generated HTTP authorization provider package after rebase * Revert changes to pom.xml for failsafe and Spring * Rebase onto master and update HTTP authorization provider * Fix broken auth provider import * Fix rebasing duplication * Fix failing auth unit test * Update authentication test to use BaseIT * Update CoreServiceAuthorizationIT to BaseIT integration structure * Update auth integration tests to use BaseIT and related classes * Remove unnecessary junit dependency and metric registry clear.
1 parent bcb9af4 commit 72cc120

File tree

20 files changed

+894
-65
lines changed

20 files changed

+894
-65
lines changed

.github/workflows/integration_tests.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
name: integration tests
2+
23
on: [push, pull_request]
4+
35
jobs:
46
maven-integration-test:
57
runs-on: ubuntu-latest
6-
name: Maven Integration Test
8+
name: integration-test-java
79
steps:
810
- uses: actions/checkout@v2
911
- name: Set up JDK 1.8

auth/.openapi-generator-ignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
settings.gradle
2+
README.md
3+
pom.xml
4+
gradle
5+
git_push.sh
6+
build.sbt
7+
build.gradle
8+
.travis*
9+
.gitignore
10+
src/main/resources/api.yaml
11+
gradle*
12+
gradle/*
13+
gradle-wrapper.*
14+
gradle**
15+
gradle/
16+
src/main/java/feast/auth/providers/http/HttpAuthorizationProvider.java
17+
src/main/java/feast/auth/providers/http/ketoadaptor/api/CheckAccessApiController.java
18+
src/main/java/feast/auth/providers/http/ketoadaptor/api/KetoAuth.java
19+
src/main/AndroidManifest.xml
20+
.openapi-generator/

auth/pom.xml

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@
1313
<name>Feast Authentication and Authorization</name>
1414

1515
<properties>
16-
<external.auth.client.package.name>feast.auth.generated.client</external.auth.client.package.name>
16+
<feast.auth.providers.http.client.package.name>feast.auth.providers.http.client
17+
</feast.auth.providers.http.client.package.name>
1718
<gson-fire-version>1.8.4</gson-fire-version>
1819
<swagger-core-version>1.5.24</swagger-core-version>
1920
<okhttp-version>3.14.7</okhttp-version>
2021
<gson-version>2.8.6</gson-version>
2122
<commons-lang3-version>3.10</commons-lang3-version>
2223
<javax-annotation-version>1.3.2</javax-annotation-version>
2324
<junit-version>4.13</junit-version>
25+
<springfox-version>2.8.0</springfox-version>
2426
</properties>
2527
<dependencies>
2628
<dependency>
@@ -60,10 +62,6 @@
6062
<groupId>com.fasterxml.jackson.core</groupId>
6163
<artifactId>jackson-databind</artifactId>
6264
</dependency>
63-
<dependency>
64-
<groupId>junit</groupId>
65-
<artifactId>junit</artifactId>
66-
</dependency>
6765
<dependency>
6866
<groupId>io.swagger</groupId>
6967
<artifactId>swagger-annotations</artifactId>
@@ -106,6 +104,55 @@
106104
<version>${mockito.version}</version>
107105
<scope>test</scope>
108106
</dependency>
107+
<dependency>
108+
<groupId>org.springframework.boot</groupId>
109+
<artifactId>spring-boot-starter-web</artifactId>
110+
</dependency>
111+
<dependency>
112+
<groupId>io.springfox</groupId>
113+
<artifactId>springfox-swagger2</artifactId>
114+
<version>${springfox-version}</version>
115+
</dependency>
116+
<dependency>
117+
<groupId>io.springfox</groupId>
118+
<artifactId>springfox-swagger-ui</artifactId>
119+
<version>${springfox-version}</version>
120+
</dependency>
121+
<dependency>
122+
<groupId>javax.xml.bind</groupId>
123+
<artifactId>jaxb-api</artifactId>
124+
<version>2.2.11</version>
125+
</dependency>
126+
<dependency>
127+
<groupId>com.fasterxml.jackson.datatype</groupId>
128+
<artifactId>jackson-datatype-jsr310</artifactId>
129+
</dependency>
130+
<dependency>
131+
<groupId>org.openapitools</groupId>
132+
<artifactId>jackson-databind-nullable</artifactId>
133+
<version>0.1.0</version>
134+
</dependency>
135+
<!-- Bean Validation API support -->
136+
<dependency>
137+
<groupId>javax.validation</groupId>
138+
<artifactId>validation-api</artifactId>
139+
</dependency>
140+
<dependency>
141+
<groupId>org.springframework.boot</groupId>
142+
<artifactId>spring-boot-starter-test</artifactId>
143+
<scope>test</scope>
144+
<exclusions>
145+
<exclusion>
146+
<groupId>org.junit.vintage</groupId>
147+
<artifactId>junit-vintage-engine</artifactId>
148+
</exclusion>
149+
</exclusions>
150+
</dependency>
151+
<dependency>
152+
<groupId>junit</groupId>
153+
<artifactId>junit</artifactId>
154+
<version>4.12</version>
155+
</dependency>
109156
</dependencies>
110157
<build>
111158
<plugins>
@@ -115,16 +162,17 @@
115162
<version>4.3.1</version>
116163
<executions>
117164
<execution>
165+
<id>client</id>
118166
<goals>
119167
<goal>generate</goal>
120168
</goals>
121169
<configuration>
122170
<inputSpec>${project.basedir}/src/main/resources/api.yaml</inputSpec>
123171
<generatorName>java</generatorName>
124-
<packageName>${external.auth.client.package.name}</packageName>
125-
<modelPackage>${external.auth.client.package.name}.model</modelPackage>
126-
<apiPackage>${external.auth.client.package.name}.api</apiPackage>
127-
<invokerPackage>${external.auth.client.package.name}.invoker</invokerPackage>
172+
<packageName>${feast.auth.providers.http.client.package.name}</packageName>
173+
<modelPackage>${feast.auth.providers.http.client.package.name}.model</modelPackage>
174+
<apiPackage>${feast.auth.providers.http.client.package.name}.api</apiPackage>
175+
<invokerPackage>${feast.auth.providers.http.client.package.name}.invoker</invokerPackage>
128176
<configOptions>
129177
<groupId>${project.groupId}</groupId>
130178
<artifactId>${project.artifactId}</artifactId>
@@ -143,7 +191,15 @@
143191
<groupId>org.apache.maven.plugins</groupId>
144192
<artifactId>maven-javadoc-plugin</artifactId>
145193
<configuration>
146-
<excludePackageNames>feast.auth.generated.client.api</excludePackageNames>
194+
<excludePackageNames>feast.auth.providers.http.client.*</excludePackageNames>
195+
</configuration>
196+
</plugin>
197+
<plugin>
198+
<groupId>org.apache.maven.plugins</groupId>
199+
<artifactId>maven-surefire-plugin</artifactId>
200+
<version>3.0.0-M4</version>
201+
<configuration>
202+
<argLine>-Xms2048m -Xmx2048m -Djdk.net.URLClassPath.disableClassPathURLCheck=true</argLine>
147203
</configuration>
148204
</plugin>
149205
<plugin>

auth/src/main/java/feast/auth/config/SecurityConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import feast.auth.authentication.DefaultJwtAuthenticationProvider;
2020
import feast.auth.authorization.AuthorizationProvider;
21-
import feast.auth.authorization.HttpAuthorizationProvider;
21+
import feast.auth.providers.http.HttpAuthorizationProvider;
2222
import java.util.ArrayList;
2323
import java.util.List;
2424
import java.util.Map;

auth/src/main/java/feast/auth/authorization/HttpAuthorizationProvider.java renamed to auth/src/main/java/feast/auth/providers/http/HttpAuthorizationProvider.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
package feast.auth.authorization;
17+
package feast.auth.providers.http;
1818

19+
import feast.auth.authorization.AuthorizationProvider;
20+
import feast.auth.authorization.AuthorizationResult;
1921
import feast.auth.config.CacheConfiguration;
20-
import feast.auth.generated.client.api.DefaultApi;
21-
import feast.auth.generated.client.invoker.ApiClient;
22-
import feast.auth.generated.client.invoker.ApiException;
23-
import feast.auth.generated.client.model.CheckAccessRequest;
22+
import feast.auth.providers.http.client.api.DefaultApi;
23+
import feast.auth.providers.http.client.invoker.ApiClient;
24+
import feast.auth.providers.http.client.invoker.ApiException;
25+
import feast.auth.providers.http.client.model.CheckAccessRequest;
2426
import feast.auth.utils.AuthUtils;
2527
import java.util.Map;
2628
import org.slf4j.Logger;
@@ -86,7 +88,7 @@ public AuthorizationResult checkAccessToProject(String projectId, Authentication
8688
try {
8789
Jwt credentials = ((Jwt) authentication.getCredentials());
8890
// Make authorization request to external service
89-
feast.auth.generated.client.model.AuthorizationResult authResult =
91+
feast.auth.providers.http.client.model.AuthorizationResult authResult =
9092
this.defaultApiClient.checkAccessPost(
9193
checkAccessRequest, "Bearer " + credentials.getTokenValue());
9294
if (authResult == null) {

auth/src/test/java/feast/auth/authorization/HttpAuthorizationProviderCachingTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@
2525
import feast.auth.config.SecurityProperties;
2626
import feast.auth.config.SecurityProperties.AuthenticationProperties;
2727
import feast.auth.config.SecurityProperties.AuthorizationProperties;
28-
import feast.auth.generated.client.api.DefaultApi;
29-
import feast.auth.generated.client.model.AuthorizationResult;
30-
import feast.auth.generated.client.model.CheckAccessRequest;
28+
import feast.auth.providers.http.HttpAuthorizationProvider;
29+
import feast.auth.providers.http.client.api.DefaultApi;
30+
import feast.auth.providers.http.client.model.AuthorizationResult;
31+
import feast.auth.providers.http.client.model.CheckAccessRequest;
3132
import java.util.HashMap;
3233
import java.util.Map;
3334
import org.junit.Test;

core/pom.xml

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
<artifactId>flyway-maven-plugin</artifactId>
6767
<version>${flyway.version}</version>
6868
</plugin>
69-
7069
</plugins>
7170
</build>
7271

@@ -315,12 +314,18 @@
315314
<version>5.2.5.RELEASE</version>
316315
<scope>test</scope>
317316
</dependency>
318-
<dependency>
319-
<groupId>org.junit.jupiter</groupId>
320-
<artifactId>junit-jupiter</artifactId>
321-
<version>5.6.2</version>
322-
<scope>test</scope>
323-
</dependency>
317+
<dependency>
318+
<groupId>org.junit.jupiter</groupId>
319+
<artifactId>junit-jupiter-api</artifactId>
320+
<version>5.6.2</version>
321+
<scope>test</scope>
322+
</dependency>
323+
<dependency>
324+
<groupId>org.junit.jupiter</groupId>
325+
<artifactId>junit-jupiter-params</artifactId>
326+
<version>5.6.2</version>
327+
<scope>test</scope>
328+
</dependency>
324329
<dependency>
325330
<groupId>org.testcontainers</groupId>
326331
<artifactId>testcontainers</artifactId>
@@ -333,6 +338,12 @@
333338
<version>1.14.3</version>
334339
<scope>test</scope>
335340
</dependency>
341+
<dependency>
342+
<groupId>sh.ory.keto</groupId>
343+
<artifactId>keto-client</artifactId>
344+
<version>0.4.4-alpha.1</version>
345+
<scope>test</scope>
346+
</dependency>
336347
<dependency>
337348
<groupId>org.testcontainers</groupId>
338349
<artifactId>postgresql</artifactId>
@@ -345,6 +356,12 @@
345356
<version>1.14.3</version>
346357
<scope>test</scope>
347358
</dependency>
359+
<dependency>
360+
<groupId>com.github.tomakehurst</groupId>
361+
<artifactId>wiremock</artifactId>
362+
<version>2.27.0</version>
363+
<scope>test</scope>
364+
</dependency>
348365
<dependency>
349366
<groupId>org.awaitility</groupId>
350367
<artifactId>awaitility</artifactId>

core/src/main/java/feast/core/config/CoreSecurityConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
@Configuration
3030
@Slf4j
31-
@ComponentScan("feast.auth")
31+
@ComponentScan("feast.auth.config")
3232
public class CoreSecurityConfig {
3333

3434
/**

core/src/main/java/feast/core/grpc/CoreServiceImpl.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import lombok.extern.slf4j.Slf4j;
3838
import net.devh.boot.grpc.server.service.GrpcService;
3939
import org.springframework.beans.factory.annotation.Autowired;
40+
import org.springframework.security.access.AccessDeniedException;
4041
import org.springframework.security.core.context.SecurityContextHolder;
4142

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

181-
accessManagementService.checkIfProjectMember(
182-
SecurityContextHolder.getContext(), request.getFeatureSet().getSpec().getProject());
183-
182+
String projectId = null;
184183
try {
184+
projectId = request.getFeatureSet().getSpec().getProject();
185+
accessManagementService.checkIfProjectMember(SecurityContextHolder.getContext(), projectId);
185186
ApplyFeatureSetResponse response = specService.applyFeatureSet(request.getFeatureSet());
186187
responseObserver.onNext(response);
187188
responseObserver.onCompleted();
@@ -192,6 +193,13 @@ public void applyFeatureSet(
192193
e);
193194
responseObserver.onError(
194195
Status.ALREADY_EXISTS.withDescription(e.getMessage()).withCause(e).asRuntimeException());
196+
} catch (AccessDeniedException e) {
197+
log.info(String.format("User prevented from accessing project: %s", projectId));
198+
responseObserver.onError(
199+
Status.PERMISSION_DENIED
200+
.withDescription(e.getMessage())
201+
.withCause(e)
202+
.asRuntimeException());
195203
} catch (Exception e) {
196204
log.error("Exception has occurred in ApplyFeatureSet method: ", e);
197205
responseObserver.onError(

core/src/main/java/feast/core/service/AccessManagementService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public void checkIfProjectMember(SecurityContext securityContext, String project
119119
AuthorizationResult result =
120120
this.authorizationProvider.checkAccessToProject(projectId, authentication);
121121
if (!result.isAllowed()) {
122-
throw new AccessDeniedException(result.getFailureReason().orElse("AccessDenied"));
122+
throw new AccessDeniedException(result.getFailureReason().orElse("Access Denied"));
123123
}
124124
}
125125
}

0 commit comments

Comments
 (0)