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

Allow unauthenticated access when Authorization is disabled and to Health Probe #927

Merged
merged 4 commits into from
Aug 4, 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
6 changes: 3 additions & 3 deletions auth/src/main/java/feast/auth/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ GrpcAuthenticationReader authenticationReader() {
}

/**
* Creates an AccessDecisionManager if authentication is enabled. This object determines the
* policy used to make authentication decisions.
* Creates an AccessDecisionManager if authorization is enabled. This object determines the policy
* used to make authorization decisions.
*
* @return AccessDecisionManager
*/
@Bean
@ConditionalOnProperty(prefix = "feast.security.authentication", name = "enabled")
@ConditionalOnProperty(prefix = "feast.security.authorization", name = "enabled")
AccessDecisionManager accessDecisionManager() {
final List<AccessDecisionVoter<?>> voters = new ArrayList<>();
voters.add(new AccessPredicateVoter());
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/feast/core/config/CoreSecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package feast.core.config;

import feast.proto.core.CoreServiceGrpc;
import io.grpc.health.v1.HealthGrpc;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.security.check.AccessPredicate;
import net.devh.boot.grpc.server.security.check.GrpcSecurityMetadataSource;
Expand Down Expand Up @@ -48,6 +49,7 @@ GrpcSecurityMetadataSource grpcSecurityMetadataSource() {
// The following endpoints allow unauthenticated access
source.set(CoreServiceGrpc.getGetFeastCoreVersionMethod(), AccessPredicate.permitAll());
source.set(CoreServiceGrpc.getUpdateStoreMethod(), AccessPredicate.permitAll());
source.set(HealthGrpc.getCheckMethod(), AccessPredicate.permitAll());
return source;
}
}
29 changes: 17 additions & 12 deletions core/src/test/java/feast/core/auth/CoreServiceAuthenticationIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import io.grpc.CallCredentials;
import io.grpc.Channel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import java.util.*;
import org.junit.ClassRule;
import org.junit.Rule;
Expand Down Expand Up @@ -121,18 +120,24 @@ public void shouldGetVersionFromFeastCoreAlways() {
assertEquals(feastProperties.getVersion(), feastCoreVersionSecure);
}

/**
* If authentication is enabled but authorization is disabled, users can still connect to Feast
* Core as anonymous users. They are not forced to authenticate.
*/
@Test
public void shouldNotAllowUnauthenticatedFeatureSetListing() {
Exception exception =
assertThrows(
StatusRuntimeException.class,
() -> {
insecureApiClient.simpleListFeatureSets("*");
});

String expectedMessage = "UNAUTHENTICATED: Authentication failed";
String actualMessage = exception.getMessage();
assertEquals(actualMessage, expectedMessage);
public void shouldAllowUnauthenticatedFeatureSetListing() {
FeatureSetProto.FeatureSet expectedFeatureSet = DataGenerator.getDefaultFeatureSet();
insecureApiClient.simpleApplyFeatureSet(expectedFeatureSet);

List<FeatureSetProto.FeatureSet> listFeatureSetsResponse =
insecureApiClient.simpleListFeatureSets("*");
FeatureSetProto.FeatureSet actualFeatureSet = listFeatureSetsResponse.get(0);

assert listFeatureSetsResponse.size() == 1;
assertEquals(
actualFeatureSet.getSpec().getProject(), expectedFeatureSet.getSpec().getProject());
assertEquals(
actualFeatureSet.getSpec().getProject(), expectedFeatureSet.getSpec().getProject());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

import feast.auth.credentials.GoogleAuthCredentials;
import feast.auth.credentials.OAuthCredentials;
import feast.proto.serving.ServingServiceGrpc;
import io.grpc.CallCredentials;
import io.grpc.health.v1.HealthGrpc;
import java.io.IOException;
import net.devh.boot.grpc.server.security.check.AccessPredicate;
import net.devh.boot.grpc.server.security.check.GrpcSecurityMetadataSource;
Expand Down Expand Up @@ -67,6 +69,10 @@ GrpcSecurityMetadataSource grpcSecurityMetadataSource() {

// Authentication is enabled for all gRPC endpoints
source.setDefault(AccessPredicate.authenticated());

// The following endpoints allow unauthenticated access
source.set(ServingServiceGrpc.getGetFeastServingInfoMethod(), AccessPredicate.permitAll());
source.set(HealthGrpc.getCheckMethod(), AccessPredicate.permitAll());
return source;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package feast.serving.it;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.testcontainers.containers.wait.strategy.Wait.forHttp;

Expand All @@ -26,7 +25,6 @@
import feast.proto.serving.ServingServiceGrpc.ServingServiceBlockingStub;
import feast.proto.types.ValueProto.Value;
import io.grpc.ManagedChannel;
import io.grpc.StatusRuntimeException;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
Expand Down Expand Up @@ -87,21 +85,21 @@ static void globalSetup() throws IOException, InitializationError, InterruptedEx
}

@Test
public void shouldNotAllowUnauthenticatedGetOnlineFeatures() {
public void shouldAllowUnauthenticatedGetOnlineFeatures() {
// apply feature set
CoreSimpleAPIClient coreClient =
AuthTestUtils.getSecureApiClientForCore(FEAST_CORE_PORT, options);
AuthTestUtils.applyFeatureSet(coreClient, PROJECT_NAME, ENTITY_ID, FEATURE_NAME);
ServingServiceBlockingStub servingStub =
AuthTestUtils.getServingServiceStub(false, FEAST_SERVING_PORT, null);
GetOnlineFeaturesRequest onlineFeatureRequest =
AuthTestUtils.createOnlineFeatureRequest(PROJECT_NAME, FEATURE_NAME, ENTITY_ID, 1);
Exception exception =
assertThrows(
StatusRuntimeException.class,
() -> {
servingStub.getOnlineFeatures(onlineFeatureRequest);
});

String expectedMessage = "UNAUTHENTICATED: Authentication failed";
String actualMessage = exception.getMessage();
assertEquals(actualMessage, expectedMessage);
GetOnlineFeaturesResponse featureResponse = servingStub.getOnlineFeatures(onlineFeatureRequest);
assertEquals(1, featureResponse.getFieldValuesCount());
Map<String, Value> fieldsMap = featureResponse.getFieldValues(0).getFieldsMap();
assertTrue(fieldsMap.containsKey(ENTITY_ID));
assertTrue(fieldsMap.containsKey(FEATURE_NAME));
((ManagedChannel) servingStub.getChannel()).shutdown();
}

@Test
Expand Down