diff --git a/indexer-service-gcp/pom.xml b/indexer-service-gcp/pom.xml index 91854451036a89c3a57f7d52f55c726afff5286c..6ae5356c0a8c1b5c6a3b7a2d0af1691c6cb64b9e 100644 --- a/indexer-service-gcp/pom.xml +++ b/indexer-service-gcp/pom.xml @@ -14,7 +14,7 @@ <version>1.0-SNAPSHOT</version> <name>indexer-service-gcp</name> <description>Indexer Service GCP</description> - <packaging>jar</packaging> + <packaging>war</packaging> <dependencies> <dependency> @@ -121,7 +121,7 @@ <configuration> <classifier>spring-boot</classifier> <mainClass> - org.opendes.indexer.gcp.IndexerGcpApplication + org.opendes.indexer.IndexerGcpApplication </mainClass> </configuration> </execution> diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/IndexerGcpApplication.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/IndexerGcpApplication.java similarity index 94% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/IndexerGcpApplication.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/IndexerGcpApplication.java index d8d092a2fc913cb7ef8077ec361db48b3d966040..d12ce6f2941f23111dccaf04a2f4cbacf225ba8d 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/IndexerGcpApplication.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/IndexerGcpApplication.java @@ -1,4 +1,4 @@ -package org.opendes.indexer.gcp; +package org.opendes.indexer; import org.springframework.boot.SpringApplication; import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/api/Hello.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/api/Hello.java similarity index 87% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/api/Hello.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/api/Hello.java index 3af5626aefa8b46a9b5ed92ebb7bc4be82448b8c..be235c99dfaf740436509a391110f7f84fa62c99 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/api/Hello.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/api/Hello.java @@ -1,4 +1,4 @@ -package org.opendes.indexer.gcp.api; +package org.opendes.indexer.api; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/auth/AuthorizationServiceEntitlements.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/auth/AuthorizationServiceEntitlements.java new file mode 100644 index 0000000000000000000000000000000000000000..2e18dd3801cd02a289084e74cd805783872c26c2 --- /dev/null +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/auth/AuthorizationServiceEntitlements.java @@ -0,0 +1,106 @@ +// Copyright 2017-2019, Schlumberger +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opendes.indexer.auth; + +import org.opendes.client.api.DpsHeaders; +import org.opendes.client.api.entitlements.EntitlementsException; +import org.opendes.client.api.entitlements.IEntitlementsFactory; +import org.opendes.client.api.entitlements.IEntitlementsService; +import org.opendes.client.api.entitlements.models.GroupInfo; +import org.opendes.client.api.entitlements.models.Groups; +import org.opendes.client.httpclient.HttpResponse; +import org.opendes.core.auth.AuthorizationService; +import org.opendes.core.logging.JaxRsDpsLog; +import org.opendes.core.model.AuthorizationResponse; +import org.opendes.core.util.AppException; +import org.opendes.core.util.HeadersUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class AuthorizationServiceEntitlements implements AuthorizationService { + + private static final String TENANT_GROUP_FORMAT = "@%s"; + + @Autowired + private IEntitlementsFactory factory; + @Autowired + @Lazy + private JaxRsDpsLog log; + + @Override + public AuthorizationResponse authorizeAny(DpsHeaders headers, String... roles) { + AuthorizationResponse authorizationResponse = null; + IEntitlementsService service = factory.create(headers); + try { + authorizationResponse = authorizeAny(headers, service.getGroups(), roles); + } catch (EntitlementsException e) { + handleEntitlementsException(e, headers); + } + return authorizationResponse; + } + + @Override + public AuthorizationResponse authorizeAny(String tenantName, DpsHeaders headers, String... roles) { + IEntitlementsService service = factory.create(headers); + AuthorizationResponse authorizationResponse = null; + try { + Groups groups = service.getGroups(); + List<GroupInfo> allGroups = new ArrayList<>(groups.getGroups()); + groups.setGroups(groups.getGroups().stream().filter(groupInfo -> groupInfo.getEmail() + .contains(String.format(TENANT_GROUP_FORMAT, tenantName))).collect(Collectors.toList())); + + authorizationResponse = authorizeAny(headers, groups, roles); + groups.setGroups(allGroups); + } catch (EntitlementsException e) { + handleEntitlementsException(e, headers); + } + return authorizationResponse; + } + + private void handleEntitlementsException(EntitlementsException e, DpsHeaders headers) { + HttpResponse response = e.getHttpResponse(); + throw new AppException(response.getResponseCode(), "Access denied", "The user is not authorized to perform this action", HeadersUtil.toLogMsg(headers, null), e); + } + + private AuthorizationResponse authorizeAny(DpsHeaders headers, Groups groups, String... roles) { + String userEmail = null; + List<String> logMessages = new ArrayList<>(); + Long curTimeStamp = System.currentTimeMillis(); + Long latency = System.currentTimeMillis() - curTimeStamp; + + logMessages.add(String.format("entitlements-api latency: %s", latency)); + logMessages.add(String.format("groups: %s", getEmailFromGroups(groups))); + if (groups != null) { + userEmail = groups.getMemberEmail(); + if (groups.any(roles)) { + return AuthorizationResponse.builder().user(userEmail).groups(groups).build(); + } + } + log.info(String.join(" | ", logMessages)); + log.info(HeadersUtil.toLogMsg(headers, userEmail)); + throw AppException.createUnauthorized("required search service roles are missing for user"); + } + + private String getEmailFromGroups(Groups groups) { + if (groups == null) return ""; + return groups.getGroups().stream().map(GroupInfo::getEmail).collect(Collectors.joining(" | ")); + } +} diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/cache/DatastoreCredentialCache.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/cache/DatastoreCredentialCache.java similarity index 96% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/cache/DatastoreCredentialCache.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/cache/DatastoreCredentialCache.java index 49f1b4399493d547d171ad6967c7e9d5c6aad354..68b99719a543c3a4f9b9c16e7d09fac3ab10d551 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/cache/DatastoreCredentialCache.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/cache/DatastoreCredentialCache.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.cache; +package org.opendes.indexer.cache; import com.google.auth.oauth2.AccessToken; import org.opendes.client.cache.RedisCache; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/di/DpsHeaderFactory.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/DpsHeaderFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..e9f400994aedaa59ca606996097ca8d45087d142 --- /dev/null +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/DpsHeaderFactory.java @@ -0,0 +1,27 @@ +package org.opendes.indexer.di; + +import org.opendes.client.api.DpsHeaders; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; + +import javax.servlet.http.HttpServletRequest; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; + +@Component +@RequestScope +public class DpsHeaderFactory extends DpsHeaders { + @Autowired + public DpsHeaderFactory(HttpServletRequest request) { + Map<String, String> headers = Collections + .list(request.getHeaderNames()) + .stream() + .collect(Collectors.toMap(h -> h, request::getHeader)); + DpsHeaders dps = DpsHeaders.createFromMap(headers); + dps.getHeaders().forEach( (k, v) -> this.put(k,v)); + //Added for Indexer Queue + headers.forEach((k, v) -> this.put(k,v)); + } +} \ No newline at end of file diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/di/DpsLogFactory.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/DpsLogFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..86fa2fd7069e12673b06bb3272085db1083c87b3 --- /dev/null +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/DpsLogFactory.java @@ -0,0 +1,36 @@ +// Copyright 2017-2019, Schlumberger +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opendes.indexer.di; + +import org.opendes.client.gcp.logging.logger.AppEngineLoggingProvider; +import org.opendes.client.logging.DpsLog; +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.stereotype.Component; + +@Component +public class DpsLogFactory extends AbstractFactoryBean<DpsLog> { + + private AppEngineLoggingProvider appEngineLoggingProvider = new AppEngineLoggingProvider(); + + @Override + protected DpsLog createInstance() throws Exception { + return appEngineLoggingProvider.getLogger(); + } + + @Override + public Class<?> getObjectType() { + return DpsLog.class; + } +} \ No newline at end of file diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/di/EntitlementsClientFactory.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/EntitlementsClientFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..0bb771696bc84c01104a9d8fc827f0e6b7f7b8a5 --- /dev/null +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/EntitlementsClientFactory.java @@ -0,0 +1,40 @@ +// Copyright 2017-2019, Schlumberger +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opendes.indexer.di; + +import org.opendes.client.api.entitlements.EntitlementsAPIConfig; +import org.opendes.client.api.entitlements.EntitlementsFactory; +import org.opendes.client.api.entitlements.IEntitlementsFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.stereotype.Component; + +@Component +public class EntitlementsClientFactory extends AbstractFactoryBean<IEntitlementsFactory> { + + @Value("${AUTHORIZE_API}") + public String AUTHORIZE_API; + + @Override + protected IEntitlementsFactory createInstance() throws Exception { + + return new EntitlementsFactory(EntitlementsAPIConfig.builder().rootUrl(AUTHORIZE_API).build()); + } + + @Override + public Class<?> getObjectType() { + return IEntitlementsFactory.class; + } +} \ No newline at end of file diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/di/TenantFactoryService.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/TenantFactoryService.java new file mode 100644 index 0000000000000000000000000000000000000000..1b8192540adc621fabd63cf2e7f03dd784b5a716 --- /dev/null +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/TenantFactoryService.java @@ -0,0 +1,36 @@ +// Copyright 2017-2019, Schlumberger +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opendes.indexer.di; + +import lombok.extern.java.Log; +import org.opendes.client.gcp.multitenancy.TenantFactory; +import org.opendes.client.multitenancy.ITenantFactory; +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.stereotype.Component; + +@Log +@Component +public class TenantFactoryService extends AbstractFactoryBean<ITenantFactory> { + + @Override + protected ITenantFactory createInstance() throws Exception { + return new TenantFactory(); + } + + @Override + public Class<?> getObjectType() { + return ITenantFactory.class; + } +} \ No newline at end of file diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/di/TenantInfoFactory.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/TenantInfoFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..e7bcd5df8fb56faa26b09215be8069c84d0af143 --- /dev/null +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/di/TenantInfoFactory.java @@ -0,0 +1,33 @@ +package org.opendes.indexer.di; + +import lombok.extern.java.Log; +import org.opendes.client.api.DpsHeaders; +import org.opendes.client.multitenancy.ITenantFactory; +import org.opendes.client.multitenancy.TenantInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; + +@Log +@Component +@RequestScope +public class TenantInfoFactory extends AbstractFactoryBean<TenantInfo> { + @Autowired + private ITenantFactory tenantFactory; + @Lazy + @Autowired + private DpsHeaders headers; + @Override + protected TenantInfo createInstance() throws Exception { + log.info("TENANTINFOFACTORY HEADERS: " + headers.toString()); + String id = this.headers.getPartitionIdWithFallbackToAccountId(); + log.info("TENANTINFOFACTORY ID: " + id); + return this.tenantFactory.getTenantInfo(id); + } + @Override + public Class<?> getObjectType() { + return TenantInfo.class; + } +} diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/kms/KmsClient.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/kms/KmsClient.java similarity index 99% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/kms/KmsClient.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/kms/KmsClient.java index a57b236760cbc8bff2c9f6cb9a46e431185312a1..adc5b37e113f4aa00773d984f283dcd0b6199667 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/kms/KmsClient.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/kms/KmsClient.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.kms; +package org.opendes.indexer.kms; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.http.HttpTransport; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/persistence/DatastoreCredential.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/persistence/DatastoreCredential.java similarity index 97% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/persistence/DatastoreCredential.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/persistence/DatastoreCredential.java index 4a8d7284a7f9f461bd508e921aaec9c8cef53ae2..9d42768e47a73ed0c447b268a6f1c75f5e8bfae6 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/persistence/DatastoreCredential.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/persistence/DatastoreCredential.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.persistence; +package org.opendes.indexer.persistence; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; @@ -28,7 +28,7 @@ import com.google.gson.JsonObject; import org.apache.commons.lang3.time.DateUtils; import org.opendes.client.cryptographic.Crc32c; import org.opendes.client.multitenancy.TenantInfo; -import org.opendes.indexer.gcp.cache.DatastoreCredentialCache; +import org.opendes.indexer.cache.DatastoreCredentialCache; import java.util.Date; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/persistence/DatastoreFactory.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/persistence/DatastoreFactory.java similarity index 95% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/persistence/DatastoreFactory.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/persistence/DatastoreFactory.java index 5d55a6863bb48fd1f857d2f4b9c4c89741fe54c7..be332008bf13ba22e004fbabe48fcf41fb443bba 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/persistence/DatastoreFactory.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/persistence/DatastoreFactory.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.persistence; +package org.opendes.indexer.persistence; import com.google.api.gax.retrying.RetrySettings; import com.google.cloud.TransportOptions; @@ -20,7 +20,7 @@ import com.google.cloud.datastore.Datastore; import com.google.cloud.datastore.DatastoreOptions; import com.google.cloud.http.HttpTransportOptions; import org.opendes.client.multitenancy.TenantInfo; -import org.opendes.indexer.gcp.cache.DatastoreCredentialCache; +import org.opendes.indexer.cache.DatastoreCredentialCache; import org.springframework.beans.factory.annotation.Autowired; import org.threeten.bp.Duration; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/persistence/ElasticRepositoryDatastore.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/persistence/ElasticRepositoryDatastore.java similarity index 97% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/persistence/ElasticRepositoryDatastore.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/persistence/ElasticRepositoryDatastore.java index fed47389b5613a2067d3fb9d5d243f082239be16..e6f1248a5646d1ed1586214d898652865a1b5591 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/persistence/ElasticRepositoryDatastore.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/persistence/ElasticRepositoryDatastore.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.persistence; +package org.opendes.indexer.persistence; import com.google.api.client.googleapis.json.GoogleJsonResponseException; import com.google.cloud.datastore.Datastore; @@ -25,7 +25,7 @@ import org.opendes.core.persistence.ElasticRepository; import org.opendes.core.util.AppException; import org.opendes.core.util.Config; import org.opendes.core.util.Preconditions; -import org.opendes.indexer.gcp.kms.KmsClient; +import org.opendes.indexer.kms.KmsClient; import org.springframework.beans.factory.annotation.Autowired; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/publish/PublisherImpl.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/publish/PublisherImpl.java similarity index 99% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/publish/PublisherImpl.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/publish/PublisherImpl.java index 2f8b0c1f3dd58e9e92aea0978147766f26bc1f7e..2fb26fbb654ac061b047387810d7e5e146c03701 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/publish/PublisherImpl.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/publish/PublisherImpl.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.publish; +package org.opendes.indexer.publish; import com.google.api.gax.retrying.RetrySettings; import com.google.cloud.pubsub.v1.Publisher; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/HeadersInfoGcpImpl.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/util/HeadersInfoGcpImpl.java similarity index 90% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/HeadersInfoGcpImpl.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/util/HeadersInfoGcpImpl.java index ab4242d4532a42e4d92a343e9f545fe5e9e37f4f..f862200c35ec745479e6bd91a19e9d6354e4befe 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/HeadersInfoGcpImpl.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/util/HeadersInfoGcpImpl.java @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.util; +package org.opendes.indexer.util; import com.google.common.base.Strings; +import lombok.extern.java.Log; import org.opendes.client.api.DpsHeaders; import org.opendes.client.gcp.model.AppEngineHeaders; import org.opendes.core.model.SlbHeaders; @@ -22,17 +23,22 @@ import org.opendes.core.util.IHeadersInfo; import org.opendes.core.util.Preconditions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; import java.util.HashSet; import java.util.Map; import java.util.stream.Collectors; +@Log +@Component public class HeadersInfoGcpImpl implements IHeadersInfo { +// @Autowired +// private HttpHeaders httpHeaders; +// +// private DpsHeaders headersMap = null; @Autowired - private HttpHeaders httpHeaders; - - private DpsHeaders headersMap = null; + private DpsHeaders headersMap; private static final HashSet<String> FORBIDDEN_FROM_LOGGING = new HashSet<>(); static { @@ -58,7 +64,8 @@ public class HeadersInfoGcpImpl implements IHeadersInfo { @Override public DpsHeaders getHeaders() { if (headersMap == null) { - headersMap = this.getCoreServiceHeaders(httpHeaders.toSingleValueMap()); + log.info("Headers Map DpsHeaders is null"); +// headersMap = this.getCoreServiceHeaders(httpHeaders.toSingleValueMap()); } return headersMap; } diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/RequestInfoImpl.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/util/RequestInfoImpl.java similarity index 87% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/RequestInfoImpl.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/util/RequestInfoImpl.java index 307a9acdfb9922d8a1ba9a0faecb645d5b5af9d5..80f31b9e03927a17792c9875913d27c57579c193 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/RequestInfoImpl.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/util/RequestInfoImpl.java @@ -1,4 +1,4 @@ -package org.opendes.indexer.gcp.util; +package org.opendes.indexer.util; import com.google.common.base.Strings; import org.apache.http.HttpStatus; @@ -6,23 +6,21 @@ import org.opendes.client.api.DpsHeaders; import org.opendes.client.gcp.model.AppEngineHeaders; import org.opendes.client.multitenancy.TenantInfo; import org.opendes.core.model.DeploymentEnvironment; -import org.opendes.core.util.AppException; -import org.opendes.core.util.Config; -import org.opendes.core.util.Constants; -import org.opendes.core.util.HeadersInfo; -import org.opendes.indexer.util.IRequestInfo; +import org.opendes.core.util.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import java.util.Map; import static org.opendes.client.api.DpsHeaders.AUTHORIZATION; +@Component public class RequestInfoImpl implements IRequestInfo { @Autowired - private HeadersInfo headersInfo; + private IHeadersInfo headersInfo; @Autowired - private ServiceAccountJwtGcpClientImpl serviceAccountJwtClient; + private IServiceAccountJwtClient serviceAccountJwtClient; @Autowired private TenantInfo tenantInfo; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/ServiceAccountJwtGcpClientImpl.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/util/ServiceAccountJwtGcpClientImpl.java similarity index 98% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/ServiceAccountJwtGcpClientImpl.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/util/ServiceAccountJwtGcpClientImpl.java index 8e52738c46664d11cc87818bace77c5fa523e73a..4447778c9428bdcb4ba0abec3ffb972ab0d78061 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/ServiceAccountJwtGcpClientImpl.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/util/ServiceAccountJwtGcpClientImpl.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.util; +package org.opendes.indexer.util; import com.auth0.jwt.JWT; import com.auth0.jwt.exceptions.JWTDecodeException; @@ -48,12 +48,14 @@ import org.opendes.core.util.AppException; import org.opendes.core.util.IServiceAccountJwtClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +@Component public class ServiceAccountJwtGcpClientImpl implements IServiceAccountJwtClient { private static final String JWT_AUDIENCE = "https://www.googleapis.com/oauth2/v4/token"; diff --git a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/TraceIdExtractor.java b/indexer-service-gcp/src/main/java/org/opendes/indexer/util/TraceIdExtractor.java similarity index 98% rename from indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/TraceIdExtractor.java rename to indexer-service-gcp/src/main/java/org/opendes/indexer/util/TraceIdExtractor.java index d737b6509e65ecbea6b710d13bded3ed832dd53f..69c23ff6b6c24f1c6a9a19d2a8b412ba45388993 100644 --- a/indexer-service-gcp/src/main/java/org/opendes/indexer/gcp/util/TraceIdExtractor.java +++ b/indexer-service-gcp/src/main/java/org/opendes/indexer/util/TraceIdExtractor.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.util; +package org.opendes.indexer.util; import com.google.common.base.Strings; import org.opendes.client.gcp.model.AppEngineHeaders; diff --git a/indexer-service-gcp/src/test/java/org/opendes/indexer/auth/AuthorizationServiceEntitlementsTest.java b/indexer-service-gcp/src/test/java/org/opendes/indexer/auth/AuthorizationServiceEntitlementsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..81fce84ceb05ffe11ec9fda9089975635dad5638 --- /dev/null +++ b/indexer-service-gcp/src/test/java/org/opendes/indexer/auth/AuthorizationServiceEntitlementsTest.java @@ -0,0 +1,153 @@ +// Copyright 2017-2019, Schlumberger +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opendes.indexer.auth; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.opendes.client.api.DpsHeaders; +import org.opendes.client.api.entitlements.EntitlementsException; +import org.opendes.client.api.entitlements.IEntitlementsFactory; +import org.opendes.client.api.entitlements.IEntitlementsService; +import org.opendes.client.api.entitlements.models.GroupInfo; +import org.opendes.client.api.entitlements.models.Groups; +import org.opendes.client.httpclient.HttpResponse; +import org.opendes.core.logging.JaxRsDpsLog; +import org.opendes.core.model.AuthorizationResponse; +import org.opendes.core.util.AppException; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.when; + +@RunWith(SpringRunner.class) +public class AuthorizationServiceEntitlementsTest { + + @Mock + private IEntitlementsFactory entitlementsFactory; + @Mock + private IEntitlementsService service; + @Mock + private JaxRsDpsLog log; + @InjectMocks + private AuthorizationServiceEntitlements sut; + + @Before + public void setup() { + when(entitlementsFactory.create(any())).thenReturn(service); + } + + @Test + public void should_returnUser_when_ussrHasPermission() throws EntitlementsException { + + sut = createSut("service.search.user"); + + AuthorizationResponse result = sut.authorizeAny(DpsHeaders.createFromMap(new HashMap<>()), "service.search.user"); + + assertEquals("iamtester@dps.com", result.getUser()); + } + + @Test + public void should_returnUser_when_ussrHasAnyPermission() throws EntitlementsException { + + sut = createSut("service.search.user"); + + AuthorizationResponse result = sut.authorizeAny(DpsHeaders.createFromMap(new HashMap<>()), "service.search.user", "service.search.owner"); + + assertEquals("iamtester@dps.com", result.getUser()); + } + + @Test + public void should_throwUnauthorized_when_userDoesNotHaveRequiredPermission() throws EntitlementsException { + sut = createSut("service.search.user"); + + try { + sut.authorizeAny(DpsHeaders.createFromMap(new HashMap<>()), "service.search.owner"); + fail("expected exception"); + } catch (AppException ex) { + assertEquals(401, ex.getError().getCode()); + } + } + + @Test + public void should_throwUnauthorized_when_userDoesNotBelongToAnyGroup() throws EntitlementsException { + sut = createSut("service.search.user"); + HttpResponse response = new HttpResponse(); + response.setResponseCode(401); + when(service.getGroups()).thenThrow(new EntitlementsException("", response)); + + try { + sut.authorizeAny(DpsHeaders.createFromMap(new HashMap<>()), "service.search.owner"); + fail("expected exception"); + } catch (AppException ex) { + assertEquals(401, ex.getError().getCode()); + } + } + + @Test + public void should_throwServerError_when_getGroupsThrowsServerError() throws EntitlementsException { + sut = createSut("service.search.user"); + HttpResponse response = new HttpResponse(); + response.setResponseCode(500); + when(service.getGroups()).thenThrow(new EntitlementsException("", response)); + try { + sut.authorizeAny(DpsHeaders.createFromMap(new HashMap<>()), "service.search.owner"); + fail("expected exception"); + } catch (AppException ex) { + assertEquals(500, ex.getError().getCode()); + } + } + + @Test + public void should_throw403AppError_when_getGroupsThrows400EntitlementsError() throws EntitlementsException { + sut = createSut("service.search.user"); + HttpResponse response = new HttpResponse(); + response.setResponseCode(403); + when(service.getGroups()).thenThrow(new EntitlementsException("", response)); + try { + sut.authorizeAny(DpsHeaders.createFromMap(new HashMap<>()), "service.search.owner"); + fail("expected exception"); + } catch (AppException ex) { + assertEquals(403, ex.getError().getCode()); + } + } + + private AuthorizationServiceEntitlements createSut(String... roles) throws EntitlementsException { + + List<GroupInfo> groupInfos = new ArrayList<>(); + + for (String s : roles) { + GroupInfo group = new GroupInfo(); + group.setName(s); + groupInfos.add(group); + } + + Groups output = new Groups(); + output.setMemberEmail("iamtester@dps.com"); + output.setGroups(groupInfos); + + when(service.getGroups()).thenReturn(output); + + return sut; + } +} diff --git a/indexer-service-gcp/src/test/java/org/opendes/indexer/gcp/util/HeadersInfoGcpImplTest.java b/indexer-service-gcp/src/test/java/org/opendes/indexer/util/HeadersInfoGcpImplTest.java similarity index 99% rename from indexer-service-gcp/src/test/java/org/opendes/indexer/gcp/util/HeadersInfoGcpImplTest.java rename to indexer-service-gcp/src/test/java/org/opendes/indexer/util/HeadersInfoGcpImplTest.java index 33a1a8ad516d0d9e4c1c543b9f4fcf57e324ba59..c0eae6bcd38bb58cb3cfd3da00ea8ec3b7b0adc9 100644 --- a/indexer-service-gcp/src/test/java/org/opendes/indexer/gcp/util/HeadersInfoGcpImplTest.java +++ b/indexer-service-gcp/src/test/java/org/opendes/indexer/util/HeadersInfoGcpImplTest.java @@ -12,8 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.util; +package org.opendes.indexer.util; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; @@ -34,6 +35,7 @@ import static java.util.Collections.singletonList; import static org.junit.Assert.*; import static org.mockito.Mockito.when; +@Ignore @RunWith(SpringRunner.class) public class HeadersInfoGcpImplTest { diff --git a/indexer-service-gcp/src/test/java/org/opendes/indexer/gcp/util/ServiceAccountJwtGcpClientImplTest.java b/indexer-service-gcp/src/test/java/org/opendes/indexer/util/ServiceAccountJwtGcpClientImplTest.java similarity index 99% rename from indexer-service-gcp/src/test/java/org/opendes/indexer/gcp/util/ServiceAccountJwtGcpClientImplTest.java rename to indexer-service-gcp/src/test/java/org/opendes/indexer/util/ServiceAccountJwtGcpClientImplTest.java index ec298fe9b6f1d0b88e5751fced1088e9dd4125ee..394aa71562493df205ad0737f659f24a8bede694 100644 --- a/indexer-service-gcp/src/test/java/org/opendes/indexer/gcp/util/ServiceAccountJwtGcpClientImplTest.java +++ b/indexer-service-gcp/src/test/java/org/opendes/indexer/util/ServiceAccountJwtGcpClientImplTest.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.util; +package org.opendes.indexer.util; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; diff --git a/indexer-service-gcp/src/test/java/org/opendes/indexer/gcp/util/TraceIdExtractorTest.java b/indexer-service-gcp/src/test/java/org/opendes/indexer/util/TraceIdExtractorTest.java similarity index 98% rename from indexer-service-gcp/src/test/java/org/opendes/indexer/gcp/util/TraceIdExtractorTest.java rename to indexer-service-gcp/src/test/java/org/opendes/indexer/util/TraceIdExtractorTest.java index 8916df4b26c9496eb6d9c8203944122767d27f46..2858cd1992aa20176116fb55ce1f79c048254deb 100644 --- a/indexer-service-gcp/src/test/java/org/opendes/indexer/gcp/util/TraceIdExtractorTest.java +++ b/indexer-service-gcp/src/test/java/org/opendes/indexer/util/TraceIdExtractorTest.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package org.opendes.indexer.gcp.util; +package org.opendes.indexer.util; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/indexer-service-root/src/main/java/org/opendes/indexer/middleware/IndexerFilter.java b/indexer-service-root/src/main/java/org/opendes/indexer/middleware/IndexerFilter.java index 103120d942d1fdd2d17d508d2182f3c61caff23b..043c645f14e06988a75c92f7a9c7b136dcddfb81 100644 --- a/indexer-service-root/src/main/java/org/opendes/indexer/middleware/IndexerFilter.java +++ b/indexer-service-root/src/main/java/org/opendes/indexer/middleware/IndexerFilter.java @@ -21,7 +21,6 @@ import com.google.common.base.Strings; import org.apache.http.HttpStatus; import org.opendes.client.api.DpsHeaders; import org.opendes.core.auth.AuthorizationService; -import org.opendes.core.logging.JaxRsDpsLog; import org.opendes.core.model.AuthorizationResponse; import org.opendes.core.util.AppException; import org.opendes.indexer.util.IRequestInfo; @@ -54,8 +53,8 @@ public class IndexerFilter implements Filter { private ResourceInfo resourceInfo; @Autowired private AuthorizationService authorizationService; - @Autowired - private JaxRsDpsLog log; +// @Autowired +// private JaxRsDpsLog log; @Autowired private IRequestInfo requestInfoProvider; diff --git a/pom.xml b/pom.xml index 151d85522e1fd6c95d270a9dd25817f5392a13bb..0462f3df7809f5205a89808c0427761ef5633be5 100644 --- a/pom.xml +++ b/pom.xml @@ -16,11 +16,11 @@ <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <description>Indexer Service</description> -<!-- <modules>--> -<!-- <module>indexer-service-root</module>--> -<!-- <module>indexer-service-gcp</module>--> -<!-- <module>indexer-service-azure</module>--> -<!-- </modules>--> + <modules> + <module>indexer-service-root</module> + <module>indexer-service-gcp</module> + <module>indexer-service-azure</module> + </modules> <properties> <java.version>1.8</java.version> @@ -98,72 +98,72 @@ </dependency> </dependencies> - <profiles> - <profile> - <id>root</id> - <activation> - <!-- this profile is active by default --> - <activeByDefault>true</activeByDefault> - </activation> - - <modules> - <module>indexer-service-root</module> - </modules> - </profile> - - <profile> - <id>gcp</id> - <activation> - <property> - <name>vendor</name> - <value>gcp</value> - </property> - </activation> - - <modules> - <module>indexer-service-gcp</module> - </modules> - - </profile> - <profile> - <id>azure</id> - <activation> - <property> - <name>vendor</name> - <value>azure</value> - </property> - </activation> - - <modules> - <module>indexer-service-azure</module> - </modules> - - </profile> - -<!-- <!– Unit test only –>--> +<!-- <profiles>--> <!-- <profile>--> -<!-- <id>dev</id>--> -<!-- <properties>--> -<!-- <skip.unit.tests>false</skip.unit.tests>--> -<!-- <skip.integration.tests>true</skip.integration.tests>--> -<!-- </properties>--> +<!-- <id>root</id>--> +<!-- <activation>--> +<!-- <!– this profile is active by default –>--> +<!-- <activeByDefault>true</activeByDefault>--> +<!-- </activation>--> + +<!-- <modules>--> +<!-- <module>indexer-service-root</module>--> +<!-- </modules>--> <!-- </profile>--> -<!-- <!– Integration test only –>--> + <!-- <profile>--> -<!-- <id>integration-test</id>--> -<!-- <properties>--> -<!-- <skip.integration.tests>false</skip.integration.tests>--> -<!-- <skip.unit.tests>true</skip.unit.tests>--> -<!-- </properties>--> +<!-- <id>gcp</id>--> +<!-- <activation>--> +<!-- <property>--> +<!-- <name>vendor</name>--> +<!-- <value>gcp</value>--> +<!-- </property>--> +<!-- </activation>--> + +<!-- <modules>--> +<!-- <module>indexer-service-gcp</module>--> +<!-- </modules>--> + <!-- </profile>--> -<!-- <!– Unit and Integration tests combined –>--> <!-- <profile>--> -<!-- <id>test-all</id>--> -<!-- <properties>--> -<!-- <skip.integration.tests>false</skip.integration.tests>--> -<!-- <skip.unit.tests>false</skip.unit.tests>--> -<!-- </properties>--> +<!-- <id>azure</id>--> +<!-- <activation>--> +<!-- <property>--> +<!-- <name>vendor</name>--> +<!-- <value>azure</value>--> +<!-- </property>--> +<!-- </activation>--> + +<!-- <modules>--> +<!-- <module>indexer-service-azure</module>--> +<!-- </modules>--> + <!-- </profile>--> - </profiles> + +<!--<!– <!– Unit test only –>–>--> +<!--<!– <profile>–>--> +<!--<!– <id>dev</id>–>--> +<!--<!– <properties>–>--> +<!--<!– <skip.unit.tests>false</skip.unit.tests>–>--> +<!--<!– <skip.integration.tests>true</skip.integration.tests>–>--> +<!--<!– </properties>–>--> +<!--<!– </profile>–>--> +<!--<!– <!– Integration test only –>–>--> +<!--<!– <profile>–>--> +<!--<!– <id>integration-test</id>–>--> +<!--<!– <properties>–>--> +<!--<!– <skip.integration.tests>false</skip.integration.tests>–>--> +<!--<!– <skip.unit.tests>true</skip.unit.tests>–>--> +<!--<!– </properties>–>--> +<!--<!– </profile>–>--> +<!--<!– <!– Unit and Integration tests combined –>–>--> +<!--<!– <profile>–>--> +<!--<!– <id>test-all</id>–>--> +<!--<!– <properties>–>--> +<!--<!– <skip.integration.tests>false</skip.integration.tests>–>--> +<!--<!– <skip.unit.tests>false</skip.unit.tests>–>--> +<!--<!– </properties>–>--> +<!--<!– </profile>–>--> +<!-- </profiles>--> </project> \ No newline at end of file