diff --git a/delta/app/src/main/resources/app.conf b/delta/app/src/main/resources/app.conf index 53aabd91a0..4bbb20f559 100644 --- a/delta/app/src/main/resources/app.conf +++ b/delta/app/src/main/resources/app.conf @@ -277,12 +277,6 @@ app { } } - # secrets encryption configuration - encryption { - password = "changeme" - salt = "salt" - } - # projection configuration projections { cluster { diff --git a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/config/AppConfig.scala b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/config/AppConfig.scala index 6721bc5e89..262108943e 100644 --- a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/config/AppConfig.scala +++ b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/config/AppConfig.scala @@ -3,7 +3,6 @@ package ch.epfl.bluebrain.nexus.delta.config import ch.epfl.bluebrain.nexus.delta.kernel.cache.CacheConfig import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.JsonLdApiConfig import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclsConfig -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.EncryptionConfig import ch.epfl.bluebrain.nexus.delta.sdk.fusion.FusionConfig import ch.epfl.bluebrain.nexus.delta.sdk.model.ServiceAccountConfig import ch.epfl.bluebrain.nexus.delta.sdk.organizations.OrganizationsConfig @@ -47,7 +46,6 @@ final case class AppConfig( schemas: SchemasConfig, serviceAccount: ServiceAccountConfig, sse: SseConfig, - encryption: EncryptionConfig, projections: ProjectionConfig, fusion: FusionConfig ) diff --git a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/DeltaModule.scala b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/DeltaModule.scala index c1988efd43..08c7f0408c 100644 --- a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/DeltaModule.scala +++ b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/DeltaModule.scala @@ -20,7 +20,6 @@ import ch.epfl.bluebrain.nexus.delta.routes.ErrorRoutes import ch.epfl.bluebrain.nexus.delta.sdk.IndexingAction.AggregateIndexingAction import ch.epfl.bluebrain.nexus.delta.sdk._ import ch.epfl.bluebrain.nexus.delta.sdk.acls.Acls -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto import ch.epfl.bluebrain.nexus.delta.sdk.fusion.FusionConfig import ch.epfl.bluebrain.nexus.delta.sdk.http.StrictEntity import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.ServiceAccount @@ -61,7 +60,6 @@ class DeltaModule(appCfg: AppConfig, config: Config)(implicit classLoader: Class make[BaseUri].from { appCfg.http.baseUri } make[StrictEntity].from { appCfg.http.strictEntityTimeout } make[ServiceAccount].from { appCfg.serviceAccount.value } - make[Crypto].from { appCfg.encryption.crypto } make[Transactors].fromResource { Transactors.init(appCfg.database) diff --git a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/IdentitiesModule.scala b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/IdentitiesModule.scala index 8c4f99737c..8c32951dbf 100644 --- a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/IdentitiesModule.scala +++ b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/IdentitiesModule.scala @@ -5,15 +5,17 @@ import akka.http.scaladsl.model.{HttpRequest, Uri} import ch.epfl.bluebrain.nexus.delta.Main.pluginsMaxPriority import ch.epfl.bluebrain.nexus.delta.config.AppConfig import ch.epfl.bluebrain.nexus.delta.kernel.cache.CacheConfig +import ch.epfl.bluebrain.nexus.delta.kernel.effect.migration._ +import ch.epfl.bluebrain.nexus.delta.kernel.search.Pagination.FromPagination import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.contexts import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.{ContextValue, RemoteContextResolution} import ch.epfl.bluebrain.nexus.delta.rdf.utils.JsonKeyOrdering import ch.epfl.bluebrain.nexus.delta.routes.IdentitiesRoutes import ch.epfl.bluebrain.nexus.delta.sdk.PriorityRoute import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclCheck +import ch.epfl.bluebrain.nexus.delta.sdk.auth.{AuthTokenProvider, OpenIdAuthService} import ch.epfl.bluebrain.nexus.delta.sdk.http.{HttpClient, HttpClientError} import ch.epfl.bluebrain.nexus.delta.sdk.identities.{Identities, IdentitiesImpl} -import ch.epfl.bluebrain.nexus.delta.kernel.search.Pagination.FromPagination import ch.epfl.bluebrain.nexus.delta.sdk.model.search.SearchParams.RealmSearchParams import ch.epfl.bluebrain.nexus.delta.sdk.model.{BaseUri, ResourceF} import ch.epfl.bluebrain.nexus.delta.sdk.realms.Realms @@ -22,7 +24,6 @@ import io.circe.Json import izumi.distage.model.definition.{Id, ModuleDef} import monix.bio.{IO, UIO} import monix.execution.Scheduler -import ch.epfl.bluebrain.nexus.delta.kernel.effect.migration._ /** * Identities module wiring config. @@ -46,6 +47,14 @@ object IdentitiesModule extends ModuleDef { IdentitiesImpl(findActiveRealm, getUserInfo, config) } + make[OpenIdAuthService].from { (httpClient: HttpClient @Id("realm"), realms: Realms) => + new OpenIdAuthService(httpClient, realms) + } + + make[AuthTokenProvider].fromEffect { (authService: OpenIdAuthService) => + AuthTokenProvider(authService) + } + many[RemoteContextResolution].addEffect(ContextValue.fromFile("contexts/identities.json").map { ctx => RemoteContextResolution.fixed(contexts.identities -> ctx) }) diff --git a/delta/plugins/composite-views/src/main/resources/composite-views.conf b/delta/plugins/composite-views/src/main/resources/composite-views.conf index efd83f4928..f4971bd402 100644 --- a/delta/plugins/composite-views/src/main/resources/composite-views.conf +++ b/delta/plugins/composite-views/src/main/resources/composite-views.conf @@ -35,6 +35,10 @@ plugins.composite-views { # the maximum batching duration. In this window, duplicated persistence ids are discarded max-time-window = 500 millis } + # the credentials for comminication with the remote source + remote-source-credentials { + type: "anonymous" + } # the minimum allowed value for periodic rebuild strategy min-interval-rebuild = 30 minutes # the interval at which a view will look for requested restarts diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViews.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViews.scala index f6b08bcfab..7c7e2c650c 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViews.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViews.scala @@ -17,7 +17,6 @@ import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model._ import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.serialization.CompositeViewFieldsJsonLdSourceDecoder import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.JsonLdApi -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.Caller import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.ExpandIri @@ -478,15 +477,15 @@ object CompositeViews { } } - def definition(validate: ValidateCompositeView, crypto: Crypto)(implicit + def definition(validate: ValidateCompositeView)(implicit clock: Clock[UIO], uuidF: UUIDF ): ScopedEntityDefinition[Iri, CompositeViewState, CompositeViewCommand, CompositeViewEvent, CompositeViewRejection] = ScopedEntityDefinition( entityType, StateMachine(None, evaluate(validate), next), - CompositeViewEvent.serializer(crypto), - CompositeViewState.serializer(crypto), + CompositeViewEvent.serializer, + CompositeViewState.serializer, Tagger[CompositeViewEvent]( { case r: CompositeViewTagAdded => Some(r.tag -> r.targetRev) @@ -515,7 +514,6 @@ object CompositeViews { fetchContext: FetchContext[CompositeViewRejection], contextResolution: ResolverContextResolution, validate: ValidateCompositeView, - crypto: Crypto, config: CompositeViewsConfig, xas: Transactors )(implicit @@ -530,7 +528,7 @@ object CompositeViews { .map { sourceDecoder => new CompositeViews( ScopedEventLog( - definition(validate, crypto), + definition(validate), config.eventLog, xas ), diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsPluginModule.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsPluginModule.scala index 72f9c25294..3f8c506708 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsPluginModule.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsPluginModule.scala @@ -7,7 +7,7 @@ import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.client.BlazegraphClient import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.client.DeltaClient import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.config.CompositeViewsConfig import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.deletion.CompositeViewsDeletionTask -import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.indexing.{CompositeProjectionLifeCycle, CompositeSinks, CompositeSpaces, CompositeViewsCoordinator, MetadataPredicates} +import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.indexing._ import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.migration.MigrateCompositeViews import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewRejection.ProjectContextRejection import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model._ @@ -22,7 +22,7 @@ import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.{ContextValue, JsonLdCon import ch.epfl.bluebrain.nexus.delta.rdf.utils.JsonKeyOrdering import ch.epfl.bluebrain.nexus.delta.sdk._ import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclCheck -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto +import ch.epfl.bluebrain.nexus.delta.sdk.auth.AuthTokenProvider import ch.epfl.bluebrain.nexus.delta.sdk.deletion.ProjectDeletionTask import ch.epfl.bluebrain.nexus.delta.sdk.directives.DeltaSchemeDirectives import ch.epfl.bluebrain.nexus.delta.sdk.fusion.FusionConfig @@ -51,9 +51,15 @@ class CompositeViewsPluginModule(priority: Int) extends ModuleDef { make[CompositeViewsConfig].fromEffect { cfg => CompositeViewsConfig.load(cfg) } - make[DeltaClient].from { (cfg: CompositeViewsConfig, as: ActorSystem[Nothing], sc: Scheduler) => - val httpClient = HttpClient()(cfg.remoteSourceClient.http, as.classicSystem, sc) - DeltaClient(httpClient, cfg.remoteSourceClient.retryDelay)(as, sc) + make[DeltaClient].from { + ( + cfg: CompositeViewsConfig, + as: ActorSystem[Nothing], + sc: Scheduler, + authTokenProvider: AuthTokenProvider + ) => + val httpClient = HttpClient()(cfg.remoteSourceClient.http, as.classicSystem, sc) + DeltaClient(httpClient, authTokenProvider, cfg.remoteSourceCredentials, cfg.remoteSourceClient.retryDelay)(as, sc) } make[BlazegraphClient].named("blazegraph-composite-indexing-client").from { @@ -91,7 +97,6 @@ class CompositeViewsPluginModule(priority: Int) extends ModuleDef { permissions: Permissions, client: ElasticSearchClient, deltaClient: DeltaClient, - crypto: Crypto, config: CompositeViewsConfig, baseUri: BaseUri ) => @@ -101,7 +106,6 @@ class CompositeViewsPluginModule(priority: Int) extends ModuleDef { permissions.fetchPermissionSet, client, deltaClient, - crypto, config.prefix, config.sources.maxSources, config.maxProjections @@ -113,7 +117,6 @@ class CompositeViewsPluginModule(priority: Int) extends ModuleDef { fetchContext: FetchContext[ContextRejection], contextResolution: ResolverContextResolution, validate: ValidateCompositeView, - crypto: Crypto, config: CompositeViewsConfig, xas: Transactors, api: JsonLdApi, @@ -124,7 +127,6 @@ class CompositeViewsPluginModule(priority: Int) extends ModuleDef { fetchContext.mapRejection(ProjectContextRejection), contextResolution, validate, - crypto, config, xas )( @@ -319,15 +321,15 @@ class CompositeViewsPluginModule(priority: Int) extends ModuleDef { )(baseUri, config.pagination, s, cr, ordering) } - make[CompositeView.Shift].from { (views: CompositeViews, base: BaseUri, crypto: Crypto) => - CompositeView.shift(views)(base, crypto) + make[CompositeView.Shift].from { (views: CompositeViews, base: BaseUri) => + CompositeView.shift(views)(base) } many[ResourceShift[_, _, _]].ref[CompositeView.Shift] - many[SseEncoder[_]].add { (crypto: Crypto, base: BaseUri) => CompositeViewEvent.sseEncoder(crypto)(base) } + many[SseEncoder[_]].add { (base: BaseUri) => CompositeViewEvent.sseEncoder(base) } - many[ScopedEventMetricEncoder[_]].add { (crypto: Crypto) => CompositeViewEvent.compositeViewMetricEncoder(crypto) } + many[ScopedEventMetricEncoder[_]].add { () => CompositeViewEvent.compositeViewMetricEncoder } many[PriorityRoute].add { ( diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/ValidateCompositeView.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/ValidateCompositeView.scala index c0b9d159c0..924492ab1d 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/ValidateCompositeView.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/ValidateCompositeView.scala @@ -4,12 +4,11 @@ import cats.syntax.all._ import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.client.DeltaClient import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.indexing.projectionIndex import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewProjection.{ElasticSearchProjection, SparqlProjection} -import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewRejection.{CrossProjectSourceForbidden, CrossProjectSourceProjectNotFound, DuplicateIds, InvalidElasticSearchProjectionPayload, InvalidEncryptionSecrets, InvalidRemoteProjectSource, PermissionIsNotDefined, TooManyProjections, TooManySources, WrappedElasticSearchClientError} -import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.{AccessToken, CrossProjectSource, ProjectSource, RemoteProjectSource} +import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewRejection.{CrossProjectSourceForbidden, CrossProjectSourceProjectNotFound, DuplicateIds, InvalidElasticSearchProjectionPayload, InvalidRemoteProjectSource, PermissionIsNotDefined, TooManyProjections, TooManySources, WrappedElasticSearchClientError} +import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.{CrossProjectSource, ProjectSource, RemoteProjectSource} import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.{CompositeViewProjection, CompositeViewRejection, CompositeViewSource, CompositeViewValue} import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.client.{ElasticSearchClient, IndexLabel} import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclCheck -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto import ch.epfl.bluebrain.nexus.delta.sdk.http.HttpClientError import ch.epfl.bluebrain.nexus.delta.sdk.http.HttpClientError.HttpClientStatusError import ch.epfl.bluebrain.nexus.delta.sdk.model.BaseUri @@ -37,7 +36,6 @@ object ValidateCompositeView { fetchPermissions: UIO[Set[Permission]], client: ElasticSearchClient, deltaClient: DeltaClient, - crypto: Crypto, prefix: String, maxSources: Int, maxProjections: Int @@ -49,13 +47,6 @@ object ValidateCompositeView { projects.fetch(cpSource.project).mapError(_ => CrossProjectSourceProjectNotFound(cpSource)).void } - def validateCrypto(token: Option[AccessToken]): IO[InvalidEncryptionSecrets.type, Unit] = token match { - case Some(AccessToken(value)) => - IO.fromEither(crypto.encrypt(value.value).flatMap(crypto.decrypt).toEither.void) - .mapError(_ => InvalidEncryptionSecrets) - case None => IO.unit - } - def validatePermission(permission: Permission) = fetchPermissions.flatMap { perms => IO.when(!perms.contains(permission))(IO.raiseError(PermissionIsNotDefined(permission))) @@ -76,7 +67,7 @@ object ValidateCompositeView { case _: ProjectSource => IO.unit case cpSource: CrossProjectSource => validateAcls(cpSource) >> validateProject(cpSource) case rs: RemoteProjectSource => - checkRemoteEvent(rs).mapError(InvalidRemoteProjectSource(rs, _)) >> validateCrypto(rs.token) + checkRemoteEvent(rs).mapError(InvalidRemoteProjectSource(rs, _)) } val validateProjection: CompositeViewProjection => IO[CompositeViewRejection, Unit] = { diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClient.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClient.scala index f387d47fcc..abce4fdd32 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClient.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClient.scala @@ -5,17 +5,17 @@ import akka.http.scaladsl.client.RequestBuilding.{Get, Head} import akka.http.scaladsl.model.ContentTypes.`application/json` import akka.http.scaladsl.model.Uri.Query import akka.http.scaladsl.model.headers.{`Last-Event-ID`, Accept} -import akka.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes, Uri} +import akka.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes} import akka.stream.alpakka.sse.scaladsl.EventSource import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.RemoteProjectSource import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.stream.CompositeBranch import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.RdfMediaTypes import ch.epfl.bluebrain.nexus.delta.rdf.graph.NQuads +import ch.epfl.bluebrain.nexus.delta.sdk.auth.{AuthTokenProvider, Credentials} import ch.epfl.bluebrain.nexus.delta.sdk.http.HttpClient import ch.epfl.bluebrain.nexus.delta.sdk.http.HttpClient.HttpResult import ch.epfl.bluebrain.nexus.delta.sdk.http.HttpClientError.HttpClientStatusError -import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.AuthToken import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectStatistics import ch.epfl.bluebrain.nexus.delta.sdk.stream.StreamConverter import ch.epfl.bluebrain.nexus.delta.sdk.syntax._ @@ -24,7 +24,6 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.offset.Offset import ch.epfl.bluebrain.nexus.delta.sourcing.offset.Offset.Start import ch.epfl.bluebrain.nexus.delta.sourcing.stream.{Elem, RemainingElems} import com.typesafe.scalalogging.Logger -import io.circe.Json import io.circe.parser.decode import fs2._ import monix.bio.{IO, UIO} @@ -72,12 +71,6 @@ trait DeltaClient { * Fetches a resource with a given id in n-quads format. */ def resourceAsNQuads(source: RemoteProjectSource, id: Iri): HttpResult[Option[NQuads]] - - /** - * Fetches a resource with a given id in n-quads format. - */ - def resourceAsJson(source: RemoteProjectSource, id: Iri): HttpResult[Option[Json]] - } object DeltaClient { @@ -86,35 +79,47 @@ object DeltaClient { private val accept = Accept(`application/json`.mediaType, RdfMediaTypes.`application/ld+json`) - final private class DeltaClientImpl(client: HttpClient, retryDelay: FiniteDuration)(implicit + final private class DeltaClientImpl( + client: HttpClient, + authTokenProvider: AuthTokenProvider, + credentials: Credentials, + retryDelay: FiniteDuration + )(implicit as: ActorSystem[Nothing], scheduler: Scheduler ) extends DeltaClient { override def projectStatistics(source: RemoteProjectSource): HttpResult[ProjectStatistics] = { - implicit val cred: Option[AuthToken] = token(source) - val statisticsEndpoint: HttpRequest = - Get( - source.endpoint / "projects" / source.project.organization.value / source.project.project.value / "statistics" - ).addHeader(accept).withCredentials - client.fromJsonTo[ProjectStatistics](statisticsEndpoint) + for { + authToken <- authTokenProvider(credentials) + request = + Get( + source.endpoint / "projects" / source.project.organization.value / source.project.project.value / "statistics" + ).addHeader(accept).withCredentials(authToken) + result <- client.fromJsonTo[ProjectStatistics](request) + } yield { + result + } } override def remaining(source: RemoteProjectSource, offset: Offset): HttpResult[RemainingElems] = { - implicit val cred: Option[AuthToken] = token(source) - val remainingEndpoint: HttpRequest = - Get(elemAddress(source) / "remaining") - .addHeader(accept) - .addHeader(`Last-Event-ID`(offset.value.toString)) - .withCredentials - client.fromJsonTo[RemainingElems](remainingEndpoint) + for { + authToken <- authTokenProvider(credentials) + request = Get(elemAddress(source) / "remaining") + .addHeader(accept) + .addHeader(`Last-Event-ID`(offset.value.toString)) + .withCredentials(authToken) + result <- client.fromJsonTo[RemainingElems](request) + } yield result } override def checkElems(source: RemoteProjectSource): HttpResult[Unit] = { - implicit val cred: Option[AuthToken] = token(source) - client(Head(elemAddress(source)).withCredentials) { - case resp if resp.status.isSuccess() => UIO.delay(resp.discardEntityBytes()) >> IO.unit - } + for { + authToken <- authTokenProvider(credentials) + result <- client(Head(elemAddress(source)).withCredentials(authToken)) { + case resp if resp.status.isSuccess() => UIO.delay(resp.discardEntityBytes()) >> IO.unit + } + } yield result } override def elems(source: RemoteProjectSource, run: CompositeBranch.Run, offset: Offset): ElemStream[Unit] = { @@ -123,10 +128,11 @@ object DeltaClient { case Offset.At(value) => Some(value.toString) } - implicit val cred: Option[AuthToken] = token(source) - def send(request: HttpRequest): Future[HttpResponse] = { - client[HttpResponse](request.withCredentials)(IO.pure(_)).runToFuture + (for { + authToken <- authTokenProvider(credentials) + result <- client[HttpResponse](request.withCredentials(authToken))(IO.pure(_)) + } yield result).runToFuture } val suffix = run match { @@ -155,37 +161,31 @@ object DeltaClient { .withQuery(typeQuery(source.selectFilter.types)) override def resourceAsNQuads(source: RemoteProjectSource, id: Iri): HttpResult[Option[NQuads]] = { - implicit val cred: Option[AuthToken] = token(source) - val resourceUrl: Uri = + val resourceUrl = source.endpoint / "resources" / source.project.organization.value / source.project.project.value / "_" / id.toString - val req = Get( - source.resourceTag.fold(resourceUrl)(t => resourceUrl.withQuery(Query("tag" -> t.value))) - ).addHeader(Accept(RdfMediaTypes.`application/n-quads`)).withCredentials - client.fromEntityTo[String](req).map(nq => Some(NQuads(nq, id))).onErrorRecover { - case HttpClientStatusError(_, StatusCodes.NotFound, _) => None - } + for { + authToken <- authTokenProvider(credentials) + req = Get( + source.resourceTag.fold(resourceUrl)(t => resourceUrl.withQuery(Query("tag" -> t.value))) + ).addHeader(Accept(RdfMediaTypes.`application/n-quads`)).withCredentials(authToken) + result <- client.fromEntityTo[String](req).map(nq => Some(NQuads(nq, id))).onErrorRecover { + case HttpClientStatusError(_, StatusCodes.NotFound, _) => None + } + } yield result } - - override def resourceAsJson(source: RemoteProjectSource, id: Iri): HttpResult[Option[Json]] = { - implicit val cred: Option[AuthToken] = token(source) - val req = Get( - source.endpoint / "resources" / source.project.organization.value / source.project.project.value / "_" / id.toString - ).addHeader(accept).withCredentials - client.toJson(req).map(Some(_)).onErrorRecover { case HttpClientStatusError(_, StatusCodes.NotFound, _) => - None - } - } - - private def token(source: RemoteProjectSource) = - source.token.map { token => AuthToken(token.value.value) } } /** * Factory method for delta clients. */ - def apply(client: HttpClient, retryDelay: FiniteDuration)(implicit + def apply( + client: HttpClient, + authTokenProvider: AuthTokenProvider, + credentials: Credentials, + retryDelay: FiniteDuration + )(implicit as: ActorSystem[Nothing], sc: Scheduler ): DeltaClient = - new DeltaClientImpl(client, retryDelay) + new DeltaClientImpl(client, authTokenProvider, credentials, retryDelay) } diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/config/CompositeViewsConfig.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/config/CompositeViewsConfig.scala index 5e89ea192a..3fc003b23e 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/config/CompositeViewsConfig.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/config/CompositeViewsConfig.scala @@ -4,6 +4,7 @@ import akka.http.scaladsl.model.Uri import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.config.BlazegraphViewsConfig.Credentials import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.config.CompositeViewsConfig.SinkConfig.SinkConfig import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.config.CompositeViewsConfig.{BlazegraphAccess, RemoteSourceClientConfig, SourcesConfig} +import ch.epfl.bluebrain.nexus.delta.sdk.auth import ch.epfl.bluebrain.nexus.delta.sdk.http.HttpClientConfig import ch.epfl.bluebrain.nexus.delta.sdk.instances._ import ch.epfl.bluebrain.nexus.delta.sdk.model.search.PaginationConfig @@ -60,7 +61,8 @@ final case class CompositeViewsConfig( elasticsearchBatch: BatchConfig, restartCheckInterval: FiniteDuration, indexingEnabled: Boolean, - sinkConfig: SinkConfig + sinkConfig: SinkConfig, + remoteSourceCredentials: auth.Credentials ) object CompositeViewsConfig { diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeView.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeView.scala index c9dd433390..ccfabdea33 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeView.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeView.scala @@ -12,7 +12,6 @@ import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.{ContextValue, RemoteCon import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.encoder.JsonLdEncoder import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.{CompactedJsonLd, ExpandedJsonLd} import ch.epfl.bluebrain.nexus.delta.sdk.ResourceShift -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdContent import ch.epfl.bluebrain.nexus.delta.sdk.model.{BaseUri, IdSegmentRef, Tags} import ch.epfl.bluebrain.nexus.delta.sdk.syntax._ @@ -168,7 +167,7 @@ object CompositeView { type Shift = ResourceShift[CompositeViewState, CompositeView, Metadata] - def shift(views: CompositeViews)(implicit baseUri: BaseUri, crypto: Crypto): Shift = + def shift(views: CompositeViews)(implicit baseUri: BaseUri): Shift = ResourceShift.withMetadata[CompositeViewState, CompositeView, Metadata]( CompositeViews.entityType, (ref, project) => views.fetch(IdSegmentRef(ref), project), diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewEvent.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewEvent.scala index a0d9aa1877..b34900d288 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewEvent.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewEvent.scala @@ -6,7 +6,6 @@ import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.ContextValue import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.JsonLdContext.keywords -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto import ch.epfl.bluebrain.nexus.delta.sdk.instances._ import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.IriEncoder import ch.epfl.bluebrain.nexus.delta.sdk.model.BaseUri @@ -170,17 +169,17 @@ object CompositeViewEvent { ) extends CompositeViewEvent @nowarn("cat=unused") - def serializer(crypto: Crypto): Serializer[Iri, CompositeViewEvent] = { + val serializer: Serializer[Iri, CompositeViewEvent] = { import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Database._ implicit val configuration: Configuration = Serializer.circeConfiguration - implicit val compositeViewValueCodec: Codec[CompositeViewValue] = CompositeViewValue.databaseCodec(crypto) + implicit val compositeViewValueCodec: Codec[CompositeViewValue] = CompositeViewValue.databaseCodec() implicit val codec: Codec.AsObject[CompositeViewEvent] = deriveConfiguredCodec[CompositeViewEvent] Serializer.dropNulls() } - def compositeViewMetricEncoder(crypto: Crypto): ScopedEventMetricEncoder[CompositeViewEvent] = + val compositeViewMetricEncoder: ScopedEventMetricEncoder[CompositeViewEvent] = new ScopedEventMetricEncoder[CompositeViewEvent] { - override def databaseDecoder: Decoder[CompositeViewEvent] = serializer(crypto).codec + override def databaseDecoder: Decoder[CompositeViewEvent] = serializer.codec override def entityType: EntityType = CompositeViews.entityType @@ -199,9 +198,9 @@ object CompositeViewEvent { ) } - def sseEncoder(crypto: Crypto)(implicit base: BaseUri): SseEncoder[CompositeViewEvent] = + def sseEncoder(implicit base: BaseUri): SseEncoder[CompositeViewEvent] = new SseEncoder[CompositeViewEvent] { - override val databaseDecoder: Decoder[CompositeViewEvent] = serializer(crypto: Crypto).codec + override val databaseDecoder: Decoder[CompositeViewEvent] = serializer.codec override def entityType: EntityType = CompositeViews.entityType diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewRejection.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewRejection.scala index fbf83d593c..20930cc620 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewRejection.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewRejection.scala @@ -204,14 +204,6 @@ object CompositeViewRejection { s"RemoteProjectSource ${remoteProjectSource.tpe} is invalid: either provided endpoint '${remoteProjectSource.endpoint}' is invalid or there are insufficient permissions to access this endpoint. " ) - /** - * Signals a rejection caused by the failure to encrypt/decrypt sensitive data (credentials) - */ - final case object InvalidEncryptionSecrets - extends CompositeViewSourceRejection( - s"Composite view plugin is using incorrect system secrets. Please contact the system administrator." - ) - /** * Rejection signalling that a projection is invalid. */ diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewSource.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewSource.scala index 42223c1bc6..50afa7a41a 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewSource.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewSource.scala @@ -1,7 +1,6 @@ package ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model import akka.http.scaladsl.model.Uri -import ch.epfl.bluebrain.nexus.delta.kernel.Secret import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSourceFields.{CrossProjectSourceFields, ProjectSourceFields, RemoteProjectSourceFields} import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.SourceType._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri @@ -14,7 +13,7 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Identity, ProjectRef} import ch.epfl.bluebrain.nexus.delta.sourcing.model.Tag.{Latest, UserTag} import ch.epfl.bluebrain.nexus.delta.sourcing.query.SelectFilter import ch.epfl.bluebrain.nexus.delta.sourcing.stream.PipeChain -import io.circe.{Encoder, Json} +import io.circe.Encoder import java.util.UUID import scala.annotation.nowarn @@ -202,8 +201,7 @@ object CompositeViewSource { resourceTag: Option[UserTag], includeDeprecated: Boolean, project: ProjectRef, - endpoint: Uri, - token: Option[AccessToken] + endpoint: Uri ) extends CompositeViewSource { override def tpe: SourceType = RemoteProjectSourceType @@ -213,7 +211,6 @@ object CompositeViewSource { Some(id), project, endpoint, - token.map(_.value), resourceSchemas, resourceTypes, resourceTag, @@ -221,11 +218,6 @@ object CompositeViewSource { ) } - final case class AccessToken(value: Secret[String]) - - @nowarn("cat=unused") - implicit private val accessTokenEncoder: Encoder[AccessToken] = Encoder.instance(_ => Json.Null) - @nowarn("cat=unused") implicit final def sourceEncoder(implicit base: BaseUri): Encoder.AsObject[CompositeViewSource] = { import io.circe.generic.extras.Configuration @@ -250,8 +242,7 @@ object CompositeViewSource { @nowarn("cat=unused") implicit final val sourceLdDecoder: JsonLdDecoder[CompositeViewSource] = { - implicit val identityLdDecoder: JsonLdDecoder[Identity] = deriveDefaultJsonLdDecoder[Identity] - implicit val accessTokenLdDecoder: JsonLdDecoder[AccessToken] = deriveDefaultJsonLdDecoder[AccessToken] + implicit val identityLdDecoder: JsonLdDecoder[Identity] = deriveDefaultJsonLdDecoder[Identity] deriveDefaultJsonLdDecoder[CompositeViewSource] } } diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewSourceFields.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewSourceFields.scala index 246d73648f..cc108102e3 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewSourceFields.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewSourceFields.scala @@ -1,8 +1,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model import akka.http.scaladsl.model.Uri -import ch.epfl.bluebrain.nexus.delta.kernel.Secret -import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.{AccessToken, CrossProjectSource, ProjectSource, RemoteProjectSource} +import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.{CrossProjectSource, ProjectSource, RemoteProjectSource} import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.SourceType._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.JsonLdContext.keywords @@ -15,7 +14,6 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.model.Tag.UserTag import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity import io.circe.Encoder -import io.circe.generic.semiauto.deriveEncoder import java.util.UUID import scala.annotation.nowarn @@ -125,7 +123,6 @@ object CompositeViewSourceFields { id: Option[Iri] = None, project: ProjectRef, endpoint: Uri, - token: Option[Secret[String]] = None, resourceSchemas: Set[Iri] = Set.empty, resourceTypes: Set[Iri] = Set.empty, resourceTag: Option[UserTag] = None, @@ -141,14 +138,10 @@ object CompositeViewSourceFields { resourceTag, includeDeprecated, project, - endpoint, - token.map(AccessToken) + endpoint ) } - @nowarn("cat=unused") - implicit private val accessTokenEncoder: Encoder[AccessToken] = deriveEncoder[AccessToken] - @nowarn("cat=unused") implicit final def sourceEncoder(implicit base: BaseUri): Encoder.AsObject[CompositeViewSourceFields] = { import io.circe.generic.extras.Configuration diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewState.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewState.scala index a7afe90638..0d66b0bd59 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewState.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewState.scala @@ -3,7 +3,6 @@ package ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject @@ -98,10 +97,10 @@ final case class CompositeViewState( object CompositeViewState { @nowarn("cat=unused") - implicit def serializer(implicit crypto: Crypto): Serializer[Iri, CompositeViewState] = { + implicit val serializer: Serializer[Iri, CompositeViewState] = { import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Database._ implicit val configuration: Configuration = Serializer.circeConfiguration - implicit val compositeViewValueCodec: Codec[CompositeViewValue] = CompositeViewValue.databaseCodec(crypto) + implicit val compositeViewValueCodec: Codec[CompositeViewValue] = CompositeViewValue.databaseCodec() implicit val codec: Codec.AsObject[CompositeViewState] = deriveConfiguredCodec[CompositeViewState] Serializer.dropNullsInjectType() } diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewValue.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewValue.scala index 67c6872582..3062181e27 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewValue.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewValue.scala @@ -1,12 +1,9 @@ package ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model import cats.data.NonEmptyMap -import cats.syntax.all._ -import ch.epfl.bluebrain.nexus.delta.kernel.Secret +//import cats.syntax.all._ import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeView.RebuildStrategy -import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.AccessToken import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ import ch.epfl.bluebrain.nexus.delta.sdk.views.IndexingRev import io.circe.generic.extras.Configuration @@ -39,16 +36,8 @@ object CompositeViewValue { @SuppressWarnings(Array("TryGet")) @nowarn("cat=unused") - def databaseCodec(crypto: Crypto)(implicit configuration: Configuration): Codec[CompositeViewValue] = { + def databaseCodec()(implicit configuration: Configuration): Codec[CompositeViewValue] = { import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Database._ - implicit val stringSecretEncryptEncoder: Encoder[Secret[String]] = Encoder.encodeString.contramap { - case Secret(value) => crypto.encrypt(value).get - } - implicit val stringSecretDecryptDecoder: Decoder[Secret[String]] = - Decoder.decodeString.emap(str => crypto.decrypt(str).map(Secret(_)).toEither.leftMap(_.getMessage)) - - implicit val accessTokenCodec: Codec.AsObject[AccessToken] = deriveConfiguredCodec[AccessToken] - implicit val finiteDurationEncoder: Encoder[FiniteDuration] = Encoder.encodeString.contramap(_.toString()) implicit val finiteDurationDecoder: Decoder[FiniteDuration] = Decoder.decodeString.emap { s => Duration(s) match { diff --git a/delta/plugins/composite-views/src/test/resources/composite-views/database/named-view-created.json b/delta/plugins/composite-views/src/test/resources/composite-views/database/named-view-created.json index 59402092db..eab09732c1 100644 --- a/delta/plugins/composite-views/src/test/resources/composite-views/database/named-view-created.json +++ b/delta/plugins/composite-views/src/test/resources/composite-views/database/named-view-created.json @@ -143,9 +143,6 @@ ], "resourceTypes": [ ], - "token": { - "value": "vv/MQBHmWaNm+TX/EigReQ==" - }, "uuid": "f8468909-a797-4b10-8b5f-000cba337bfa" }, { diff --git a/delta/plugins/composite-views/src/test/resources/composite-views/database/named-view-updated.json b/delta/plugins/composite-views/src/test/resources/composite-views/database/named-view-updated.json index 3f5899facf..d9e1fc851e 100644 --- a/delta/plugins/composite-views/src/test/resources/composite-views/database/named-view-updated.json +++ b/delta/plugins/composite-views/src/test/resources/composite-views/database/named-view-updated.json @@ -143,9 +143,6 @@ ], "resourceTypes": [ ], - "token": { - "value": "vv/MQBHmWaNm+TX/EigReQ==" - }, "uuid": "f8468909-a797-4b10-8b5f-000cba337bfa" }, { diff --git a/delta/plugins/composite-views/src/test/resources/composite-views/database/view-created.json b/delta/plugins/composite-views/src/test/resources/composite-views/database/view-created.json index 76eca6aac5..2d57981259 100644 --- a/delta/plugins/composite-views/src/test/resources/composite-views/database/view-created.json +++ b/delta/plugins/composite-views/src/test/resources/composite-views/database/view-created.json @@ -141,9 +141,6 @@ ], "resourceTypes": [ ], - "token": { - "value": "vv/MQBHmWaNm+TX/EigReQ==" - }, "uuid": "f8468909-a797-4b10-8b5f-000cba337bfa" }, { diff --git a/delta/plugins/composite-views/src/test/resources/composite-views/database/view-state.json b/delta/plugins/composite-views/src/test/resources/composite-views/database/view-state.json index 2f835e6ef7..4c26c2ad28 100644 --- a/delta/plugins/composite-views/src/test/resources/composite-views/database/view-state.json +++ b/delta/plugins/composite-views/src/test/resources/composite-views/database/view-state.json @@ -154,9 +154,6 @@ ], "resourceTypes": [ ], - "token": { - "value": "vv/MQBHmWaNm+TX/EigReQ==" - }, "uuid": "f8468909-a797-4b10-8b5f-000cba337bfa" }, { diff --git a/delta/plugins/composite-views/src/test/resources/composite-views/database/view-updated.json b/delta/plugins/composite-views/src/test/resources/composite-views/database/view-updated.json index 2d937a8985..010c5f7b94 100644 --- a/delta/plugins/composite-views/src/test/resources/composite-views/database/view-updated.json +++ b/delta/plugins/composite-views/src/test/resources/composite-views/database/view-updated.json @@ -141,9 +141,6 @@ ], "resourceTypes": [ ], - "token": { - "value": "vv/MQBHmWaNm+TX/EigReQ==" - }, "uuid": "f8468909-a797-4b10-8b5f-000cba337bfa" }, { diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewDecodingSpec.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewDecodingSpec.scala index 01f8e4c8bc..ff2f89174b 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewDecodingSpec.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewDecodingSpec.scala @@ -2,7 +2,6 @@ package ch.epfl.bluebrain.nexus.delta.plugins.compositeviews import akka.http.scaladsl.model.Uri import cats.data.NonEmptyList -import ch.epfl.bluebrain.nexus.delta.kernel.Secret import ch.epfl.bluebrain.nexus.delta.kernel.utils.UUIDF import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeView.Interval import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewProjectionFields.{ElasticSearchProjectionFields, SparqlProjectionFields} @@ -112,8 +111,7 @@ class CompositeViewDecodingSpec RemoteProjectSourceFields( Some(iri"http://music.com/sources/songs"), ProjectGen.project("remote_demo", "songs").ref, - Uri("https://example2.nexus.com"), - Some(Secret("mytoken")) + Uri("https://example2.nexus.com") ) ), NonEmptyList.of( @@ -146,8 +144,7 @@ class CompositeViewDecodingSpec RemoteProjectSourceFields( None, ProjectGen.project("remote_demo", "songs").ref, - Uri("https://example2.nexus.com"), - Some(Secret("mytoken")) + Uri("https://example2.nexus.com") ) ), NonEmptyList.of( diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewFactorySuite.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewFactorySuite.scala index d291ad3bac..cc42d2b4e3 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewFactorySuite.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewFactorySuite.scala @@ -1,7 +1,6 @@ package ch.epfl.bluebrain.nexus.delta.plugins.compositeviews import akka.http.scaladsl.model.Uri -import ch.epfl.bluebrain.nexus.delta.kernel.Secret import ch.epfl.bluebrain.nexus.delta.kernel.utils.UUIDF import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewProjection._ import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewProjectionFields.{ElasticSearchProjectionFields, SparqlProjectionFields} @@ -60,7 +59,6 @@ class CompositeViewFactorySuite extends BioSuite { Some(remoteSourceId), ProjectRef.unsafe("org", "remoteproject"), Uri("http://example.com/remote-endpoint"), - Some(Secret("secret token")), schemas, types, tag, @@ -140,8 +138,7 @@ class CompositeViewFactorySuite extends BioSuite { tag, includeDeprecated, remoteSourceFields.project, - remoteSourceFields.endpoint, - remoteSourceFields.token.map(s => AccessToken(s)) + remoteSourceFields.endpoint ) ) } diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsFixture.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsFixture.scala index 0239c9ccc1..e11fb62765 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsFixture.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsFixture.scala @@ -2,20 +2,19 @@ package ch.epfl.bluebrain.nexus.delta.plugins.compositeviews import akka.http.scaladsl.model.Uri import cats.data.NonEmptyList -import ch.epfl.bluebrain.nexus.delta.kernel.Secret import ch.epfl.bluebrain.nexus.delta.kernel.utils.UUIDF import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.config.CompositeViewsConfig import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.config.CompositeViewsConfig.{BlazegraphAccess, RemoteSourceClientConfig, SinkConfig, SourcesConfig} import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeView.Interval import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewProjection.{ElasticSearchProjection, SparqlProjection} import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewProjectionFields.{ElasticSearchProjectionFields, SparqlProjectionFields} -import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.{AccessToken, CrossProjectSource, ProjectSource, RemoteProjectSource} +import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.{CrossProjectSource, ProjectSource, RemoteProjectSource} import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSourceFields.{CrossProjectSourceFields, ProjectSourceFields, RemoteProjectSourceFields} import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.{permissions, CompositeViewFields, TemplateSparqlConstructQuery} import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.ContextValue.ContextObject import ch.epfl.bluebrain.nexus.delta.rdf.syntax._ import ch.epfl.bluebrain.nexus.delta.sdk.ConfigFixtures -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto +import ch.epfl.bluebrain.nexus.delta.sdk.auth.Credentials import ch.epfl.bluebrain.nexus.delta.sdk.generators.ProjectGen import ch.epfl.bluebrain.nexus.delta.sdk.views.IndexingRev import ch.epfl.bluebrain.nexus.delta.sourcing.config.BatchConfig @@ -32,8 +31,6 @@ import scala.concurrent.duration._ trait CompositeViewsFixture extends ConfigFixtures with EitherValuable { - val crypto: Crypto = Crypto("changeme", "salt") - val alwaysValidate: ValidateCompositeView = (_, _) => IO.unit val query = @@ -70,8 +67,7 @@ trait CompositeViewsFixture extends ConfigFixtures with EitherValuable { val remoteProjectFields = RemoteProjectSourceFields( Some(iri"http://example.com/remote-project-source"), ProjectRef(Label.unsafe("org"), Label.unsafe("remoteproject")), - Uri("http://example.com/remote-endpoint"), - Some(Secret("secret token")) + Uri("http://example.com/remote-endpoint") ) val esProjectionFields = ElasticSearchProjectionFields( @@ -125,8 +121,7 @@ trait CompositeViewsFixture extends ConfigFixtures with EitherValuable { None, false, ProjectRef(Label.unsafe("org"), Label.unsafe("remoteproject")), - Uri("http://example.com/remote-endpoint"), - Some(AccessToken(Secret("secret token"))) + Uri("http://example.com/remote-endpoint") ) val esProjection = ElasticSearchProjection( @@ -182,7 +177,8 @@ trait CompositeViewsFixture extends ConfigFixtures with EitherValuable { batchConfig, 3.seconds, false, - SinkConfig.Batch + SinkConfig.Batch, + Credentials.Anonymous ) } diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsSpec.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsSpec.scala index 47a97b864a..68602a63fe 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsSpec.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsSpec.scala @@ -59,7 +59,6 @@ class CompositeViewsSpec fetchContext, ResolverContextResolution(rcr), alwaysValidate, - crypto, config, xas ).accepted diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClientSpec.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClientSpec.scala index 89884a9d4f..2403661675 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClientSpec.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClientSpec.scala @@ -11,12 +11,12 @@ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.RouteResult import akka.stream.scaladsl.Source import akka.testkit.TestKit -import ch.epfl.bluebrain.nexus.delta.kernel.Secret -import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.{AccessToken, RemoteProjectSource} +import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.RemoteProjectSource import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.stream.CompositeBranch import ch.epfl.bluebrain.nexus.delta.rdf.RdfMediaTypes import ch.epfl.bluebrain.nexus.delta.rdf.graph.NQuads import ch.epfl.bluebrain.nexus.delta.sdk.ConfigFixtures +import ch.epfl.bluebrain.nexus.delta.sdk.auth.{AuthTokenProvider, Credentials} import ch.epfl.bluebrain.nexus.delta.sdk.http.{HttpClient, HttpClientConfig} import ch.epfl.bluebrain.nexus.delta.sdk.marshalling.QueryParamsUnmarshalling import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectStatistics @@ -141,7 +141,8 @@ class DeltaClientSpec } implicit private val httpCfg: HttpClientConfig = httpClientConfig - private val deltaClient = DeltaClient(HttpClient(), 1.second) + private val deltaClient = + DeltaClient(HttpClient(), AuthTokenProvider.fixedForTest(token), Credentials.Anonymous, 1.second) private val source = RemoteProjectSource( iri"http://example.com/remote-project-source", @@ -151,14 +152,11 @@ class DeltaClientSpec None, includeDeprecated = false, project, - Uri("http://localhost:8080/v1"), - Some(AccessToken(Secret(token))) + Uri("http://localhost:8080/v1") ) private val unknownProjectSource = source.copy(project = ProjectRef.unsafe("org", "unknown")) - private val unknownToken = source.copy(token = Some(AccessToken(Secret("invalid")))) - "Getting project statistics" should { "work" in { @@ -168,10 +166,6 @@ class DeltaClientSpec "fail if project is unknown" in { deltaClient.projectStatistics(unknownProjectSource).rejected.errorCode.value shouldEqual StatusCodes.NotFound } - - "fail if token is invalid" in { - deltaClient.projectStatistics(unknownToken).rejected.errorCode.value shouldEqual StatusCodes.Forbidden - } } "Getting remaining information" should { @@ -187,10 +181,6 @@ class DeltaClientSpec .errorCode .value shouldEqual StatusCodes.NotFound } - - "fail if token is invalid" in { - deltaClient.remaining(unknownToken, Offset.Start).rejected.errorCode.value shouldEqual StatusCodes.Forbidden - } } "Getting elems" should { @@ -215,23 +205,11 @@ class DeltaClientSpec "return None if tag doesn't exist" in { deltaClient.resourceAsNQuads(source.copy(resourceTag = invalidTag), resourceId).accepted shouldEqual None } - - "fail if token is invalid" in { - deltaClient - .resourceAsNQuads(unknownToken, resourceId) - .rejected - .errorCode - .value shouldEqual StatusCodes.Forbidden - } } "Checking elems" should { "work" in { deltaClient.checkElems(source).accepted } - "fail if token is invalid" in { - deltaClient.checkElems(unknownToken).rejected.errorCode.value shouldEqual StatusCodes.Forbidden - } } - } diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/indexing/CompositeIndexingSuite.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/indexing/CompositeIndexingSuite.scala index f7acf381ce..75029dc674 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/indexing/CompositeIndexingSuite.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/indexing/CompositeIndexingSuite.scala @@ -279,8 +279,7 @@ abstract class CompositeIndexingSuite(sinkConfig: SinkConfig, query: SparqlConst None, includeDeprecated = false, project3, - Uri("https://bbp.epfl.ch/nexus"), - None + Uri("https://bbp.epfl.ch/nexus") ) private val contextJson = jsonContentOf("indexing/music-context.json") diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/migration/MigrateCompositeViewsSuite.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/migration/MigrateCompositeViewsSuite.scala index 02de03ce67..ba57456b0f 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/migration/MigrateCompositeViewsSuite.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/migration/MigrateCompositeViewsSuite.scala @@ -8,7 +8,6 @@ import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.migration.MigrateCom import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewEvent.{CompositeViewCreated, CompositeViewUpdated} import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.{CompositeViewEvent, CompositeViewState, CompositeViewValue} import ch.epfl.bluebrain.nexus.delta.rdf.syntax.iriStringContextSyntax -import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto import ch.epfl.bluebrain.nexus.delta.sourcing.Transactors import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, Tag} import ch.epfl.bluebrain.nexus.delta.sourcing.implicits._ @@ -33,10 +32,9 @@ class MigrateCompositeViewsSuite extends BioSuite with Doobie.Fixture with Class implicit private lazy val xas: Transactors = doobie() - private val crypto: Crypto = Crypto("changeme", "salt") - private val eventSerializer = CompositeViewEvent.serializer(crypto) + private val eventSerializer = CompositeViewEvent.serializer implicit val eventGet: Get[CompositeViewEvent] = eventSerializer.getValue - private val stateSerializer = CompositeViewState.serializer(crypto) + private val stateSerializer = CompositeViewState.serializer implicit val stateGet: Get[CompositeViewState] = stateSerializer.getValue private def assertMigratedValue(value: CompositeViewValue, rev: Int)(implicit loc: Location): Unit = { diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewsSerializationSuite.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewsSerializationSuite.scala index e3de54b30c..5fe7b05f33 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewsSerializationSuite.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewsSerializationSuite.scala @@ -33,9 +33,9 @@ class CompositeViewsSerializationSuite extends SerializationSuite with Composite // format: on ) - private val eventSerializer = CompositeViewEvent.serializer(crypto) - private val sseEncoder = CompositeViewEvent.sseEncoder(crypto) - private val metricEncoder = CompositeViewEvent.compositeViewMetricEncoder(crypto) + private val eventSerializer = CompositeViewEvent.serializer + private val sseEncoder = CompositeViewEvent.sseEncoder + private val metricEncoder = CompositeViewEvent.compositeViewMetricEncoder eventsMapping.foreach { case (event, (database, sse)) => test(s"Correctly serialize ${event.getClass.getName}") { @@ -91,7 +91,7 @@ class CompositeViewsSerializationSuite extends SerializationSuite with Composite private val jsonState = jsonContentOf("/composite-views/database/view-state.json") - private val stateSerializer = CompositeViewState.serializer(crypto) + private val stateSerializer = CompositeViewState.serializer test(s"Correctly serialize a CompositeViewState") { stateSerializer.codec(state).equalsIgnoreArrayOrder(jsonState) diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsRoutesSpec.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsRoutesSpec.scala index 3883c51a7e..3d7203d638 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsRoutesSpec.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsRoutesSpec.scala @@ -60,7 +60,6 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { fetchContext, ResolverContextResolution(rcr), alwaysValidate, - crypto, config, xas ).accepted diff --git a/delta/plugins/search/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/search/SearchScopeInitializationSpec.scala b/delta/plugins/search/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/search/SearchScopeInitializationSpec.scala index 3e4cfd70f2..1ab8afcb6b 100644 --- a/delta/plugins/search/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/search/SearchScopeInitializationSpec.scala +++ b/delta/plugins/search/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/search/SearchScopeInitializationSpec.scala @@ -40,7 +40,6 @@ class SearchScopeInitializationSpec fetchContext, ResolverContextResolution(rcr), alwaysValidate, - crypto, config, xas ).accepted diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/StoragePluginModule.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/StoragePluginModule.scala index 537f7b93ac..03f4609bfd 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/StoragePluginModule.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/StoragePluginModule.scala @@ -24,7 +24,7 @@ import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.{ContextValue, RemoteCon import ch.epfl.bluebrain.nexus.delta.rdf.utils.JsonKeyOrdering import ch.epfl.bluebrain.nexus.delta.sdk._ import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclCheck -import ch.epfl.bluebrain.nexus.delta.sdk.auth.{AuthTokenProvider, Credentials, OpenIdAuthService} +import ch.epfl.bluebrain.nexus.delta.sdk.auth.{AuthTokenProvider, Credentials} import ch.epfl.bluebrain.nexus.delta.sdk.deletion.ProjectDeletionTask import ch.epfl.bluebrain.nexus.delta.sdk.directives.DeltaSchemeDirectives import ch.epfl.bluebrain.nexus.delta.sdk.fusion.FusionConfig @@ -37,7 +37,6 @@ import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext.ContextRejection import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ApiMappings -import ch.epfl.bluebrain.nexus.delta.sdk.realms.Realms import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolverContextResolution import ch.epfl.bluebrain.nexus.delta.sdk.sse.SseEncoder import ch.epfl.bluebrain.nexus.delta.sourcing.Transactors @@ -147,14 +146,6 @@ class StoragePluginModule(priority: Int) extends ModuleDef { many[ResourceShift[_, _, _]].ref[Storage.Shift] - make[OpenIdAuthService].from { (httpClient: HttpClient @Id("realm"), realms: Realms) => - new OpenIdAuthService(httpClient, realms) - } - - make[AuthTokenProvider].fromEffect { (authService: OpenIdAuthService) => - AuthTokenProvider(authService) - } - make[Files] .fromEffect { ( diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageRejection.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageRejection.scala index c849084912..e7dbd44bfe 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageRejection.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageRejection.scala @@ -195,17 +195,6 @@ object StorageRejection { s"The provided permissions '${permissions.mkString(",")}' are not defined in the collection of allowed permissions." ) - /** - * Signals a rejection caused by the failure to encrypt/decrypt sensitive data (credentials) - */ - final case class InvalidEncryptionSecrets(tpe: StorageType, details: String) - extends StorageRejection( - s"Storage type '$tpe' is using incorrect system secrets. Please contact the system administrator.", - Some( - s"Encryption/decryption for storage type '$tpe' fails due to wrong configuration for password or salt. Details '$details'." - ) - ) - /** * Signals a rejection caused when interacting with other APIs when fetching a resource */ @@ -241,16 +230,15 @@ object StorageRejection { implicit final val storageRejectionHttpResponseFields: HttpResponseFields[StorageRejection] = HttpResponseFields { - case RevisionNotFound(_, _) => StatusCodes.NotFound - case TagNotFound(_) => StatusCodes.NotFound - case StorageNotFound(_, _) => StatusCodes.NotFound - case DefaultStorageNotFound(_) => StatusCodes.NotFound - case ResourceAlreadyExists(_, _) => StatusCodes.Conflict - case IncorrectRev(_, _) => StatusCodes.Conflict - case ProjectContextRejection(rej) => rej.status - case StorageNotAccessible(_, _) => StatusCodes.BadRequest - case InvalidEncryptionSecrets(_, _) => StatusCodes.InternalServerError - case _ => StatusCodes.BadRequest + case RevisionNotFound(_, _) => StatusCodes.NotFound + case TagNotFound(_) => StatusCodes.NotFound + case StorageNotFound(_, _) => StatusCodes.NotFound + case DefaultStorageNotFound(_) => StatusCodes.NotFound + case ResourceAlreadyExists(_, _) => StatusCodes.Conflict + case IncorrectRev(_, _) => StatusCodes.Conflict + case ProjectContextRejection(rej) => rej.status + case StorageNotAccessible(_, _) => StatusCodes.BadRequest + case _ => StatusCodes.BadRequest } } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/auth/AuthTokenProvider.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/auth/AuthTokenProvider.scala index 5d2dbd5e67..8d3057a074 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/auth/AuthTokenProvider.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/auth/AuthTokenProvider.scala @@ -23,7 +23,10 @@ object AuthTokenProvider { def apply(authService: OpenIdAuthService): UIO[AuthTokenProvider] = { KeyValueStore[ClientCredentials, ParsedToken]().map(cache => new CachingOpenIdAuthTokenProvider(authService, cache)) } - def anonymousForTest: AuthTokenProvider = new AnonymousAuthTokenProvider + def anonymousForTest: AuthTokenProvider = new AnonymousAuthTokenProvider + def fixedForTest(token: String): AuthTokenProvider = new AuthTokenProvider { + override def apply(credentials: Credentials): UIO[Option[AuthToken]] = UIO.pure(Some(AuthToken(token))) + } } private class AnonymousAuthTokenProvider extends AuthTokenProvider { diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/crypto/Crypto.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/crypto/Crypto.scala deleted file mode 100644 index d4659f7aea..0000000000 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/crypto/Crypto.scala +++ /dev/null @@ -1,76 +0,0 @@ -package ch.epfl.bluebrain.nexus.delta.sdk.crypto - -import java.nio.charset.StandardCharsets.UTF_8 -import java.util.Base64 -import javax.crypto.Cipher._ -import javax.crypto.spec.{PBEKeySpec, SecretKeySpec} -import javax.crypto.{Cipher, SecretKey, SecretKeyFactory} -import scala.util.Try - -/** - * Provides encryption and decryption functionality - */ -final class Crypto private (derivedKey: SecretKey) { - - /** - * @return - * the key in its primary encoded format - */ - private[crypto] def encoded: Array[Byte] = derivedKey.getEncoded - - /** - * Encrypts the given input with the provided AES secret key. - * - * @return - * a right with the encrypted string in base64 encoding or a left with the error message - */ - def encrypt(input: String): Try[String] = - Try { - val cipher = Cipher.getInstance(Crypto.transformation) - cipher.init(ENCRYPT_MODE, derivedKey) - val bytes = cipher.doFinal(input.getBytes(UTF_8)) - Base64.getEncoder.encodeToString(bytes) - } - - /** - * Decrypts the given base64 encoded input with the provided AES secret key. - * - * @return - * a right with the decrypted string or a left with the error message - */ - def decrypt(input: String): Try[String] = - Try { - val cipher = Cipher.getInstance(Crypto.transformation) - cipher.init(DECRYPT_MODE, derivedKey) - val bytes = cipher.doFinal(Base64.getDecoder.decode(input)) - new String(bytes, UTF_8) - } - - override def toString: String = "SECRET" -} - -object Crypto { - private val transformation = "AES" - - /** - * Derives a suitable AES-256 secret key from a given password and a salt. - */ - private def deriveKey(password: String, salt: String): SecretKey = { - val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512") - val spec = new PBEKeySpec(password.toCharArray, salt.getBytes(UTF_8), 1000, 256) - val key = factory.generateSecret(spec) - new SecretKeySpec(key.getEncoded, "AES") - } - - /** - * Creates a [[Crypto]] for AES-256 - * - * @param password - * the password to use for encryption - * @param salt - * the salt to use for encryption - */ - final def apply(password: String, salt: String): Crypto = - new Crypto(deriveKey(password, salt)) - -} diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/crypto/EncryptionConfig.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/crypto/EncryptionConfig.scala deleted file mode 100644 index c260fd0585..0000000000 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/crypto/EncryptionConfig.scala +++ /dev/null @@ -1,22 +0,0 @@ -package ch.epfl.bluebrain.nexus.delta.sdk.crypto - -import ch.epfl.bluebrain.nexus.delta.kernel.Secret -import pureconfig.ConfigReader -import pureconfig.generic.semiauto.deriveReader - -/** - * The encryption of sensitive fields configuration - * - * @param password - * the password for the symmetric-key cyphering algorithm - * @param salt - * the salt value - */ -final case class EncryptionConfig(password: Secret[String], salt: Secret[String]) { - val crypto: Crypto = Crypto(password.value, salt.value) -} - -object EncryptionConfig { - implicit final val encryptionConfigReader: ConfigReader[EncryptionConfig] = - deriveReader[EncryptionConfig] -} diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/crypto/CryptoSpec.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/crypto/CryptoSpec.scala deleted file mode 100644 index 5e2dc15d59..0000000000 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/crypto/CryptoSpec.scala +++ /dev/null @@ -1,25 +0,0 @@ -package ch.epfl.bluebrain.nexus.delta.sdk.crypto - -import ch.epfl.bluebrain.nexus.testkit.{EitherValuable, TestHelpers} -import org.scalatest.matchers.should.Matchers -import org.scalatest.wordspec.AnyWordSpecLike - -import java.util.Base64 - -class CryptoSpec extends AnyWordSpecLike with Matchers with TestHelpers with EitherValuable { - - private val secretKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" - - "The Crypto object" should { - - "always generate the same key for a given password" in { - val crypto = Crypto("changeme", "salt") - Base64.getEncoder.encodeToString(crypto.encoded) shouldEqual "FB4G2MHn/q6PXqpNkE1F5wBG7Ndsd9FtyeLcNQL0G40=" - } - - "encode and decode secrets" in { - val crypto = Crypto(genString(32), genString(16)) - crypto.decrypt(crypto.encrypt(secretKey).get).get shouldEqual secretKey - } - } -} diff --git a/docs/src/main/paradox/docs/getting-started/running-nexus/configuration/index.md b/docs/src/main/paradox/docs/getting-started/running-nexus/configuration/index.md index 4021e5ce7c..efe5bcea4a 100644 --- a/docs/src/main/paradox/docs/getting-started/running-nexus/configuration/index.md +++ b/docs/src/main/paradox/docs/getting-started/running-nexus/configuration/index.md @@ -69,12 +69,6 @@ This feature can be turned on via the flag `app.automatic-provisioning.enabled`. @link:[The `automatic-provisioning` section](https://github.com/BlueBrain/nexus/blob/$git.branch$/delta/app/src/main/resources/app.conf#L197){ open=new } of the configuration defines the project provisioning configuration. -## Encryption configuration - -Nexus Delta uses symmetric encryption to secure sensitive data information (tokens and passwords). - -@link:[The `encryption` section](https://github.com/BlueBrain/nexus/blob/$git.branch$/delta/app/src/main/resources/app.conf#L276){ open=new } of the configuration defines the encryption configuration. - ## Fusion configuration When fetching a resource, Nexus Delta allows to return a redirection to its representation in Fusion by providing `text/html` in the `Accept` header. @@ -121,6 +115,8 @@ The composite views plugin configuration can be found @link:[here](https://githu There are several configuration flags related to tweaking the range of values allowed for sources, projections and rebuild interval. +Authentication for remote sources can be specified in three different ways. The value of `plugins.composite-views.remote-source-credentials` should be speficied in the same way as remote storages, as shown @ref:[here](#remote-storage-configuration) + ### Storage plugin configuration The storage plugin configuration can be found @link:[here](https://github.com/BlueBrain/nexus/blob/$git.branch$/delta/plugins/storage/src/main/resources/storage.conf){ open=new }. diff --git a/docs/src/main/paradox/docs/releases/index.md b/docs/src/main/paradox/docs/releases/index.md index ed1ad237a6..7d672fcd30 100644 --- a/docs/src/main/paradox/docs/releases/index.md +++ b/docs/src/main/paradox/docs/releases/index.md @@ -27,7 +27,7 @@ The latest stable release is **v1.8.0** released on **14.06.2023**. - @ref:[Resource payloads can't contain fields starting by `_` anymore](../delta/api/resources-api.md) - @ref:[The endpoint for fetching indexing errors as SSEs changed](../delta/api/views/index.md#fetch-indexing-failures-as-sses) -- @ref:[Credentials for storages can now only be defined at the configuration level](../releases/v1.9-release-notes.md#storages) +- @ref:[Credentials for storages can now only be defined at the configuration level](../releases/v1.9-release-notes.md#remote-storages) ### New features / enhancements diff --git a/docs/src/main/paradox/docs/releases/v1.8-to-v1.9-migration.md b/docs/src/main/paradox/docs/releases/v1.8-to-v1.9-migration.md index 2092f0f458..235a7f896c 100644 --- a/docs/src/main/paradox/docs/releases/v1.8-to-v1.9-migration.md +++ b/docs/src/main/paradox/docs/releases/v1.8-to-v1.9-migration.md @@ -41,3 +41,11 @@ The following logs should appear in Delta: ``` After this completes, the environment variable can be removed and Delta restarted. + +## Remote authentication + +Currently, both remote storages and composite views with remote sources can hold auth tokens for communications with these remote endpoints. In v1.9, we now expect authentication to be dealt with in the Delta configuration + +A remote storage might currently have a token stored in the storage definition. In 1.9, this should be moved to `plugins.storage.storages.remote-disk.credentials`, as shown @ref:[here](../getting-started/running-nexus/configuration/index.md#remote-storage-configuration) + +A composite view might currently have a token stored in the view definition. In 1.9, this should be moved to `plugins.composite-views.remote-source-credentials`, as shown @ref:[here](../getting-started/running-nexus/configuration/index.md#composite-views-plugin-configuration) diff --git a/docs/src/main/paradox/docs/releases/v1.9-release-notes.md b/docs/src/main/paradox/docs/releases/v1.9-release-notes.md index eee009ea23..d5d71099e5 100644 --- a/docs/src/main/paradox/docs/releases/v1.9-release-notes.md +++ b/docs/src/main/paradox/docs/releases/v1.9-release-notes.md @@ -71,7 +71,7 @@ The different requests to Elasticsearch are now compressed by default allowing t ### Composite views -To enhance performance of indexing of composite views, Nexus Delta introduces the following features. +New features enhance performance of indexing of composite views, as well as authentication changes for views which incorporate projects on remote Delta instances #### Batching queries to the intermediate space @@ -91,6 +91,12 @@ Preserving the intermediate space also reduces the fragmentation of the Blazegra @ref:[More information](../delta/api/views/composite-view-api.md#batching-queries-to-the-intermediate-space) +#### Remote authentication + +Rather than storing an auth token in the composite view, it is now expected to specify an authentication method in the Delta configuration + +@ref:[More information](../getting-started/running-nexus/configuration/index.md#composite-views-plugin-configuration) + ### Elasticsearch Views The Elasticsearch mapping of an Elasticsearch View can be retrieved. @@ -119,6 +125,8 @@ Tarball archives are no longer supported due to unnecessary restrictions. ZIP is ### Storages +### Remote Storages + Storages can no longer be created with credentials that would get stored: * For S3 storages, this would be `accessKey`/`secretKey`. diff --git a/tests/docker/config/delta-postgres.conf b/tests/docker/config/delta-postgres.conf index 17f686a802..f142eaa3e7 100644 --- a/tests/docker/config/delta-postgres.conf +++ b/tests/docker/config/delta-postgres.conf @@ -68,6 +68,12 @@ plugins { composite-views { min-interval-rebuild = 5 seconds sink-config = batch + remote-source-credentials { + type: "client-credentials" + user: "delta" + password: "shhh" + realm: "internal" + } } elasticsearch { diff --git a/tests/src/test/resources/kg/views/composite/composite-view.json b/tests/src/test/resources/kg/views/composite/composite-view.json index 58a1e0b9b8..4d5a650e97 100644 --- a/tests/src/test/resources/kg/views/composite/composite-view.json +++ b/tests/src/test/resources/kg/views/composite/composite-view.json @@ -18,8 +18,7 @@ "@id": "https://music.example.com/sources/songs", "@type": "RemoteProjectEventStream", "project": "{{org2}}/songs", - "endpoint": "{{remoteEndpoint}}", - "token": "{{token}}" + "endpoint": "{{remoteEndpoint}}" } ], "projections": [ diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/CompositeViewsSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/CompositeViewsSpec.scala index 9d5a255b4d..f40a8305c4 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/CompositeViewsSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/CompositeViewsSpec.scala @@ -126,8 +126,6 @@ class CompositeViewsSpec extends BaseSpec { "creating the view" should { - def jerryToken = tokensMap.get(Jerry).credentials.token() - "create a composite view" in { val view = jsonContentOf( "/kg/views/composite/composite-view.json", @@ -136,7 +134,6 @@ class CompositeViewsSpec extends BaseSpec { "org" -> orgId, "org2" -> orgId, "remoteEndpoint" -> "http://delta:8080/v1", - "token" -> jerryToken, "bandQuery" -> bandQuery, "albumQuery" -> albumQuery ): _* @@ -162,7 +159,6 @@ class CompositeViewsSpec extends BaseSpec { "org" -> orgId, "org2" -> orgId, "remoteEndpoint" -> "http://delta:8080/v1/other", - "token" -> jerryToken, "bandQuery" -> bandQuery, "albumQuery" -> albumQuery ): _* @@ -173,32 +169,6 @@ class CompositeViewsSpec extends BaseSpec { } } - "reject creating a composite view with wrong remote source token" in { - val view = jsonContentOf( - "/kg/views/composite/composite-view.json", - replacements( - Jerry, - "org" -> orgId, - "org2" -> orgId, - "remoteEndpoint" -> "http://delta:8080/v1", - "token" -> s"${jerryToken}wrong", - "bandQuery" -> bandQuery, - "albumQuery" -> albumQuery - ): _* - ) - - deltaClient.put[Json](s"/views/$orgId/bands/composite2", view, Jerry) { (json, response) => - response.status shouldEqual StatusCodes.BadRequest - json shouldEqual jsonContentOf( - "/kg/views/composite/composite-source-token-reject.json", - replacements( - Jerry, - "project" -> s"$orgId/songs" - ): _* - ) - } - } - "reject creating a composite view with remote source endpoint with a wrong hostname" in { val view = jsonContentOf( "/kg/views/composite/composite-view.json", @@ -207,7 +177,6 @@ class CompositeViewsSpec extends BaseSpec { "org" -> orgId, "org2" -> orgId, "remoteEndpoint" -> "http://fail.does.not.exist.at.all.asndkajbskhabsdfjhabsdfjkh/v1", - "token" -> jerryToken, "bandQuery" -> bandQuery, "albumQuery" -> albumQuery ): _*