Commit 94eb08b1 authored by Diego Molteni's avatar Diego Molteni
Browse files

fix: branch 'master' into aws-randombucket

parent 9975ca33
Pipeline #76081 passed with stages
in 13 minutes and 27 seconds
......@@ -198,4 +198,4 @@
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.
limitations under the License.
\ No newline at end of file
# 3rd-Party Software License Notice
Generated by fossa-cli (https://github.com/fossas/fossa-cli).
This software includes the following software and licenses:
......@@ -568,8 +567,8 @@ The following software have components provided under the terms of this license:
- isarray (from https://www.npmjs.com/package/isarray)
- isarray (from https://www.npmjs.com/package/isarray)
- isstream (from https://github.com/rvagg/isstream)
- jmespath (from https://www.npmjs.com/package/jmespath)
- jmespath (from https://github.com/jmespath/jmespath.py)
- jmespath (from https://www.npmjs.com/package/jmespath)
- js-sha256 (from https://www.npmjs.com/package/js-sha256)
- jsbn (from https://www.npmjs.com/package/jsbn)
- json-bigint (from https://www.npmjs.com/package/json-bigint)
......@@ -898,3 +897,5 @@ The following software have components provided under the terms of this license:
- jmespath (from https://www.npmjs.com/package/jmespath)
- querystring (from https://www.npmjs.com/package/querystring)
- sax (from https://www.npmjs.com/package/sax)
......@@ -23,7 +23,7 @@ FROM node:${docker_node_image_version} as runtime-builder
ADD ./ /service
WORKDIR /service
RUN apk --no-cache add --virtual native-deps g++ gcc libgcc libstdc++ linux-headers make python \
RUN apk --no-cache add --virtual native-deps g++ gcc libgcc libstdc++ linux-headers make python3 \
&& npm install --quiet node-gyp -g \
&& npm install --quiet \
&& npm run build \
......@@ -39,7 +39,7 @@ FROM node:${docker_node_image_version} as release
COPY --from=runtime-builder /service/artifact /seistore-service
WORKDIR /seistore-service
RUN apk --no-cache add --virtual native-deps g++ gcc libgcc libstdc++ linux-headers make python \
RUN apk --no-cache add --virtual native-deps g++ gcc libgcc libstdc++ linux-headers make python3 \
&& addgroup appgroup \
&& adduser --disabled-password --gecos --shell appuser --ingroup appgroup \
&& chown -R appuser:appgroup /seistore-service \
......
......@@ -2089,7 +2089,7 @@ definitions:
description: Storage location for the bucket.
admin:
type: string
description: Administrator for the subproject.
description: Administrator for the subproject. Note that this field is used as a principal identifer for entitlements-svc and be configured using the env variable USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC in the Seismic DMS runtime.
ltag:
type: string
description: Legal tag for the subproject.
......@@ -2161,7 +2161,7 @@ definitions:
properties:
email:
type: string
description: Email address of the user.
description: Email address of the user. Note that this field is used as a principal identifer for entitlements-svc and be configured using the env variable USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC in the Seismic DMS runtime.
path:
type: string
description: Seismic store path in the format sd://tenant/subproject.
......@@ -2180,7 +2180,7 @@ definitions:
properties:
email:
type: string
description: Email address of the user.
description: Email address of the user. Note that this field is used as a principal identifer for entitlements-svc and be configured using the env variable USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC in the Seismic DMS runtime.
path:
type: string
description: Seismic store path in the format sd://tenant/subproject.
......
......@@ -2099,7 +2099,7 @@ definitions:
description: Storage location for the bucket
admin:
type: string
description: Administrator for the subproject
description: Administrator for the subproject. Note that this field is used as a principal identifer for entitlements-svc and be configured using the env variable USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC in the Seismic DMS runtime.
ltag:
type: string
description: Legal tag for the subproject
......@@ -2172,7 +2172,7 @@ definitions:
properties:
email:
type: string
description: Email address of the user
description: Email address of the user. Note that this field is used as a principal identifer for entitlements-svc and be configured using the env variable USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC in the Seismic DMS runtime.
path:
type: string
description: Seismic store path in the format sd://tenant/subproject
......@@ -2191,7 +2191,7 @@ definitions:
properties:
email:
type: string
description: Email address of the user
description: Email address of the user. Note that this field is used as a principal identifer for entitlements-svc and be configured using the env variable USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC in the Seismic DMS runtime.
path:
type: string
description: Seismic store path in the format sd://tenant/subproject
......
......@@ -66,6 +66,9 @@ export interface ConfigModel {
FEATURE_FLAG_CCM_INTERACTION: boolean;
CCM_SERVICE_URL: string;
CCM_TOKEN_SCOPE: string;
USER_ID_CLAIM_FOR_SDMS: string;
USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC: string;
USER_ASSOCIATION_SVC_PROVIDER: string;
}
export abstract class Config implements IConfig {
......@@ -193,6 +196,13 @@ export abstract class Config implements IConfig {
public static CCM_SERVICE_URL = undefined;
public static CCM_TOKEN_SCOPE = undefined;
// Principal Identifier for Seismic DMS and Entitlements Svc
public static USER_ID_CLAIM_FOR_SDMS: string;
public static USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC: string;
// Function to convert principal identiifer to user using CCM
public static USER_ASSOCIATION_SVC_PROVIDER: string;
public static setCloudProvider(cloudProvider: string) {
Config.CLOUDPROVIDER = cloudProvider;
if (Config.CLOUDPROVIDER === undefined) {
......@@ -289,6 +299,12 @@ export abstract class Config implements IConfig {
Config.checkRequiredConfig(Config.JWT_AUDIENCE, 'JWT_AUDIENCE');
}
// Subject identifiers for
Config.USER_ID_CLAIM_FOR_SDMS = model.USER_ID_CLAIM_FOR_SDMS;
Config.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC = model.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC;
Config.USER_ASSOCIATION_SVC_PROVIDER = model.USER_ASSOCIATION_SVC_PROVIDER;
// auto generated configurations
Config.ORGANIZATION_NS = Config.ORGANIZATION_NS + '-' + Config.SERVICE_ENV;
Config.SEISMIC_STORE_NS = Config.SEISMIC_STORE_NS + '-' + Config.SERVICE_ENV;
......
......@@ -13,7 +13,7 @@
// limitations under the License.
import { Config, ConfigFactory } from '../../config';
import {AWSSSMhelper} from './ssmhelper';
import { AWSSSMhelper } from './ssmhelper';
@ConfigFactory.register('aws')
export class AWSConfig extends Config {
......@@ -86,7 +86,11 @@ export class AWSConfig extends Config {
FEATURE_FLAG_CCM_INTERACTION: process.env.FEATURE_FLAG_CCM_INTERACTION ?
process.env.FEATURE_FLAG_CCM_INTERACTION === 'true' : false,
CCM_SERVICE_URL: process.env.CCM_SERVICE_URL || '',
CCM_TOKEN_SCOPE: process.env.CCM_TOKEN_SCOPE || ''
CCM_TOKEN_SCOPE: process.env.CCM_TOKEN_SCOPE || '',
USER_ID_CLAIM_FOR_SDMS: process.env.USER_ID_CLAIM_FOR_SDMS ? process.env.USER_ID_CLAIM_FOR_SDMS : 'subid',
USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC: process.env.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC ?
process.env.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC : 'email',
USER_ASSOCIATION_SVC_PROVIDER: process.env.USER_ASSOCIATION_SVC_PROVIDER
});
}
......
......@@ -41,6 +41,10 @@ export class AzureConfig extends Config {
// max len for a group name in DE
public static DES_GROUP_CHAR_LIMIT = 256;
// cosmo throughput settings
public static COSMO_THROUGHPUT: number;
public static COSMO_MAX_THROUGHPUT: number;
public async init(): Promise<void> {
......@@ -80,6 +84,10 @@ export class AzureConfig extends Config {
AzureConfig.SERVICE_AUTH_PROVIDER_CREDENTIAL = // If not set as secret try to load from envs
AzureConfig.SERVICE_AUTH_PROVIDER_CREDENTIAL || process.env.SERVICE_AUTH_PROVIDER_CREDENTIAL;
// cosmo throughput settings
AzureConfig.COSMO_THROUGHPUT = +process.env.COSMO_THROUGHPUT || 2500;
AzureConfig.COSMO_MAX_THROUGHPUT = +process.env.COSMO_MAX_THROUGHPUT || 25000;
// init generic configurations
await Config.initServiceConfiguration({
SERVICE_ENV: process.env.APP_ENVIRONMENT_IDENTIFIER,
......@@ -131,7 +139,11 @@ export class AzureConfig extends Config {
FEATURE_FLAG_CCM_INTERACTION: process.env.FEATURE_FLAG_CCM_INTERACTION ?
process.env.FEATURE_FLAG_CCM_INTERACTION === 'true' : false,
CCM_SERVICE_URL: AzureConfig.CCM_SERVICE_URL,
CCM_TOKEN_SCOPE: AzureConfig.CCM_TOKEN_SCOPE
CCM_TOKEN_SCOPE: AzureConfig.CCM_TOKEN_SCOPE,
USER_ID_CLAIM_FOR_SDMS: process.env.USER_ID_CLAIM_FOR_SDMS ? process.env.USER_ID_CLAIM_FOR_SDMS : 'subid',
USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC: process.env.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC ?
process.env.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC : 'email',
USER_ASSOCIATION_SVC_PROVIDER: process.env.USER_ASSOCIATION_SVC_PROVIDER
});
// initialize app insight
......
......@@ -42,7 +42,12 @@ export class AzureCosmosDbDAO extends AbstractJournal {
key: connectionParams.key
});
const { database } = await cosmosClient.databases.createIfNotExists({id: 'seistore-' + this.dataPartition + '-db'});
const { container } = await database.containers.createIfNotExists({ id: 'seistore-' + this.dataPartition + '-container', partitionKey: '/key' });
const { container } = await database.containers.createIfNotExists({
id: 'seistore-' + this.dataPartition + '-container',
throughput: AzureConfig.COSMO_THROUGHPUT,
maxThroughput: AzureConfig.COSMO_MAX_THROUGHPUT,
partitionKey: '/key'
});
AzureCosmosDbDAO.containerCache[containerId] = container;
return AzureCosmosDbDAO.containerCache[containerId];
}
......
......@@ -156,7 +156,13 @@ export class ConfigGoogle extends Config {
FEATURE_FLAG_CCM_INTERACTION: process.env.FEATURE_FLAG_CCM_INTERACTION ?
process.env.FEATURE_FLAG_CCM_INTERACTION === 'true' : false,
CCM_SERVICE_URL: process.env.CCM_SERVICE_URL,
CCM_TOKEN_SCOPE: process.env.CCM_TOKEN_SCOPE
CCM_TOKEN_SCOPE: process.env.CCM_TOKEN_SCOPE,
USER_ID_CLAIM_FOR_SDMS: process.env.USER_ID_CLAIM_FOR_SDMS ? process.env.USER_ID_CLAIM_FOR_SDMS : 'subid',
USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC: process.env.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC ?
process.env.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC : 'email',
USER_ASSOCIATION_SVC_PROVIDER: process.env.USER_ASSOCIATION_SVC_PROVIDER ?
process.env.USER_ASSOCIATION_SVC_PROVIDER
: 'ccm-internal'
});
}
......
......@@ -28,7 +28,7 @@ export class IbmConfig extends Config {
public static COS_SUBUSER_SECRET_ACCESS_KEY: string;
public static COS_TEMP_CRED_EXPITY: string;
// IBM KeyCloak
// IBM KeyCloak
public static KEYCLOAK_BASEURL: string;
public static KEYCLOAK_URL_TOKEN: string;
public static KEYCLOAK_REALM: string;
......@@ -111,7 +111,7 @@ export class IbmConfig extends Config {
IbmConfig.DOC_DB_QUERY_RESULT_LIMIT = process.env.DOC_DB_QUERY_RESULT_LIMIT;
IbmConfig.DOC_DB_QUERY_RESULT_LIMIT_VALUE = parseInt(process.env.DOC_DB_QUERY_RESULT_LIMIT_VALUE, 10);
IbmConfig.DES_SERVICE_APPKEY = 'na'
IbmConfig.DES_SERVICE_APPKEY = 'na';
Config.checkRequiredConfig(IbmConfig.DES_SERVICE_HOST_COMPLIANCE, 'DES_SERVICE_HOST_COMPLIANCE');
Config.checkRequiredConfig(IbmConfig.DES_SERVICE_HOST_ENTITLEMENT, 'DES_SERVICE_HOST_ENTITLEMENT');
Config.checkRequiredConfig(IbmConfig.DES_SERVICE_HOST_STORAGE, 'DES_SERVICE_HOST_STORAGE');
......@@ -178,7 +178,11 @@ export class IbmConfig extends Config {
FEATURE_FLAG_CCM_INTERACTION: process.env.FEATURE_FLAG_CCM_INTERACTION ?
process.env.FEATURE_FLAG_CCM_INTERACTION === 'true' : false,
CCM_SERVICE_URL: IbmConfig.CCM_SERVICE_URL,
CCM_TOKEN_SCOPE: IbmConfig.CCM_TOKEN_SCOPE
CCM_TOKEN_SCOPE: IbmConfig.CCM_TOKEN_SCOPE,
USER_ID_CLAIM_FOR_SDMS: process.env.USER_ID_CLAIM_FOR_SDMS ? process.env.USER_ID_CLAIM_FOR_SDMS : 'subid',
USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC: process.env.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC ?
process.env.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC : 'email',
USER_ASSOCIATION_SVC_PROVIDER: process.env.USER_ASSOCIATION_SVC_PROVIDER
});
......
......@@ -14,8 +14,9 @@
// limitations under the License.
// ============================================================================
export { DESEntitlement } from './entitlement';
export { DESCompliance } from './compliance';
export { DESEntitlement } from './entitlement';
export { DESStorage } from './storage';
export { DESUserAssociation } from './user-association-svc/ccm-internal';
export { DESUtils } from './utils';
export { DESUserAssociation } from './user-association';
import request from 'request-promise';
import { AuthProviderFactory } from '../../auth';
import { Config, DataEcosystemCoreFactory } from '../../cloud';
import { Cache, Error } from '../../shared';
import { AbstractUserAssociationSvcProvider, UserAssocationServiceFactory } from '../user-association';
// this impl is used when the USER_ASSOCIATION_SVC_PROVIDER env variable is set to decorator identifier ccm-internal
@UserAssocationServiceFactory.register('ccm-internal')
export class DESUserAssociation extends AbstractUserAssociationSvcProvider {
private static _cache: Cache<string>;
public async convertPrincipalIdentifierToEmail(principalIdentifier: string,
dataPartitionID: string): Promise<string> {
if (!DESUserAssociation._cache) {
DESUserAssociation._cache = new Cache<string>('ccm-user-exchange');
}
const cacheKey = principalIdentifier;
const cacheLookupResult = await DESUserAssociation._cache.get(cacheKey);
if (cacheLookupResult) {
return cacheLookupResult;
}
const dataecosystem = DataEcosystemCoreFactory.build(Config.CLOUDPROVIDER);
const credential = await AuthProviderFactory
.build(Config.SERVICE_AUTH_PROVIDER)
.generateScopedAuthCredential([Config.CCM_TOKEN_SCOPE]);
const options = {
headers: {
'Accept': 'application/json',
'AppKey': Config.DES_SERVICE_APPKEY,
'Authorization': 'Bearer ' + credential.access_token,
'Content-Type': 'application/json'
},
url: Config.CCM_SERVICE_URL + '/' + dataecosystem.getUserAssociationSvcBaseUrlPath()
+ '/users/' + principalIdentifier + '/information',
};
options.headers[dataecosystem.getDataPartitionIDRestHeaderName()] = dataPartitionID;
try {
const results = await request.get(options);
const userEmail = JSON.parse(results)['email'];
await DESUserAssociation._cache.set(cacheKey, userEmail);
return userEmail;
} catch (error) {
if (error && error.statusCode === 404 && error.message.includes('User not found')) {
await DESUserAssociation._cache.set(cacheKey, principalIdentifier);
return principalIdentifier;
}
throw (Error.makeForHTTPRequest(error, '[ccm-user-association-service]'));
}
}
}
\ No newline at end of file
......@@ -14,64 +14,48 @@
// limitations under the License.
// ============================================================================
import request from 'request-promise';
import { AuthProviderFactory } from '../auth';
import { Config, DataEcosystemCoreFactory } from '../cloud';
import { Cache, Error } from '../shared';
export class DESUserAssociation {
private static _cache: Cache<string>;
// User association details cached for an hour
private static _cacheEntryTTL = 3600;
public static async convertSubIdToEmail(subId: string, dataPartitionID: string): Promise<string> {
import { Error } from '../shared';
export interface IUserAssociationSvcProvider {
convertPrincipalIdentifierToEmail(principalIdentifier: string, dataPartitionID: string): Promise<string>;
}
export abstract class AbstractUserAssociationSvcProvider implements IUserAssociationSvcProvider {
public abstract convertPrincipalIdentifierToEmail(principalIdentifier: string,
dataPartitionID: string): Promise<string>;
}
export class UserAssociationFactoryBuilder {
public static register(identifer: string) {
return (target: any) => {
if (UserAssociationFactoryBuilder.providers[identifer]) {
UserAssociationFactoryBuilder.providers[identifer].push(target);
} else {
UserAssociationFactoryBuilder.providers[identifer] = [target];
}
};
}
if (!this._cache) {
this._cache = new Cache<string>('subid-to-email-mapping');
public static build(identifer: string, referenceAbstraction: any, args: { [key: string]: any; } = {}) {
if (identifer === undefined || identifer === 'unknown') {
throw (Error.make(Error.Status.UNKNOWN,
`Unrecognized user assocation service provider: ${identifer}`));
}
const cacheKey = subId;
const cacheLookupResult = await this._cache.get(cacheKey);
if (cacheLookupResult) {
return cacheLookupResult;
for (const provider of UserAssociationFactoryBuilder.providers[identifer]) {
if (provider.prototype instanceof referenceAbstraction) {
return new provider(args);
}
}
throw (Error.make(Error.Status.UNKNOWN,
`The user-association-service-provider builder that extend ${referenceAbstraction} has not been found`));
}
const dataecosystem = DataEcosystemCoreFactory.build(Config.CLOUDPROVIDER);
const credential = await AuthProviderFactory
.build(Config.SERVICE_AUTH_PROVIDER)
.generateScopedAuthCredential([Config.CCM_TOKEN_SCOPE]);
const options = {
headers: {
'Accept': 'application/json',
'AppKey': Config.DES_SERVICE_APPKEY,
'Authorization': 'Bearer ' + credential.access_token,
'Content-Type': 'application/json'
},
url: Config.CCM_SERVICE_URL + '/' + dataecosystem.getUserAssociationSvcBaseUrlPath()
+ '/users/' + subId + '/information',
};
options.headers[dataecosystem.getDataPartitionIDRestHeaderName()] = dataPartitionID;
try {
const results = await request.get(options);
const userEmail = JSON.parse(results)['email'];
await this._cache.set(cacheKey, userEmail);
return userEmail;
private static providers: { [key: string]: any[]; } = {};
}
} catch (error) {
if (error && error.statusCode === 404 && error.message.includes('User not found')) {
await this._cache.set(cacheKey, subId);
return subId;
}
throw (Error.makeForHTTPRequest(error, '[ccm-user-association-service]'));
}
export class UserAssocationServiceFactory extends UserAssociationFactoryBuilder {
public static build(identifier: string): AbstractUserAssociationSvcProvider {
return UserAssociationFactoryBuilder.build(identifier, AbstractUserAssociationSvcProvider);
}
}
\ No newline at end of file
......@@ -16,11 +16,11 @@
import { Request as expRequest, Response as expResponse } from 'express';
import { v4 as uuidv4 } from 'uuid';
import { DatasetModel } from '.';
import { Auth, AuthRoles } from '../../auth';
import { Config, JournalFactoryTenantClient, LoggerFactory, StorageFactory } from '../../cloud';
import { DESStorage, DESUserAssociation, DESUtils } from '../../dataecosystem';
import { DESStorage, DESUtils } from '../../dataecosystem';
import { UserAssocationServiceFactory } from '../../dataecosystem/user-association';
import { Error, Feature, FeatureFlags, Params, Response, Utils } from '../../shared';
import { SubprojectAuth, SubProjectDAO, SubProjectModel } from '../subproject';
import { TenantDAO, TenantModel } from '../tenant';
......@@ -30,6 +30,7 @@ import { IWriteLockSession, Locker } from './locker';
import { DatasetOP } from './optype';
import { DatasetParser } from './parser';
export class DatasetHandler {
// handler for the [ /dataset ] endpoints
......@@ -324,7 +325,8 @@ export class DatasetHandler {
if (FeatureFlags.isEnabled(Feature.CCM_INTERACTION) && convertSubIdToEmail) {
if (!Utils.isEmail(datasetOUT.created_by)) {
const dataPartition = DESUtils.getDataPartitionID(tenant.esd);
const userEmail = await DESUserAssociation.convertSubIdToEmail(datasetOUT.created_by, dataPartition);
const userEmail = await UserAssocationServiceFactory.build(Config.USER_ASSOCIATION_SVC_PROVIDER).
convertPrincipalIdentifierToEmail(datasetOUT.created_by, dataPartition);
datasetOUT.created_by = userEmail;
}
......
......@@ -16,6 +16,7 @@
import { Request as expRequest } from 'express';
import { DatasetModel } from '.';
import { Config } from '../../cloud';
import { Error, Params, Utils } from '../../shared';
export class DatasetParser {
......@@ -45,7 +46,8 @@ export class DatasetParser {
const dataset = this.createDatasetModelFromRequest(req);
dataset.ltag = (req.headers.ltag) as string;
dataset.type = req.body ? req.body.type : undefined;
dataset.created_by = Utils.getSubIDFromPayload(req.headers.authorization) ||
dataset.created_by = Utils.getPropertyFromTokenPayload
(req.headers.authorization, Config.USER_ID_CLAIM_FOR_SDMS) ||
Utils.getSubFromPayload(req.headers.authorization) ||
undefined;
......
......@@ -21,7 +21,7 @@ import { SeistoreFactory } from '../../cloud/seistore';
import { Error, Feature, FeatureFlags, Response, Utils } from '../../shared';
import { SubprojectAuth, SubProjectDAO } from '../subproject';
import { TenantDAO } from '../tenant';
import { ImpersonationTokenModel, ImpersonationTokenContextModel } from './model';
import { ImpersonationTokenContextModel, ImpersonationTokenModel } from './model';
import { ImpersonationTokenOps } from './optype';
import { ImpersonationTokenParser } from './parser';
......@@ -29,7 +29,7 @@ export class ImpersonationTokenHandler {
// handler for the [ /impersonation-token ] endpoints
public static async handler(req: expRequest, res: expResponse, op: ImpersonationTokenOps) {
try{
try {
// the impersonation token endpoints are not available with impersonation tokens
if (Auth.isImpersonationToken(req.headers.authorization)) {
......@@ -73,7 +73,7 @@ export class ImpersonationTokenHandler {
if (appEmailV2 !== appEmail) {
await Auth.isAppAuthorized(tenant, appEmailV2);
} else {
throw(error);
throw (error);
}
}
}
......@@ -121,8 +121,8 @@ export class ImpersonationTokenHandler {
// generate the impersonation token credential token (the auth credential)
const authProvider = AuthProviderFactory.build(Config.SERVICE_AUTH_PROVIDER);
const scopes = [authProvider.getClientID()];
if(Config.DES_TARGET_AUDIENCE) {
scopes.push(Config.DES_TARGET_AUDIENCE)
if (Config.DES_TARGET_AUDIENCE) {
scopes.push(Config.DES_TARGET_AUDIENCE);
}
const impersonationToken = authProvider.convertToImpersonationTokenModel(
await authProvider.generateScopedAuthCredential(scopes));
......@@ -170,8 +170,8 @@ export class ImpersonationTokenHandler {
try {
await Auth.isAppAuthorized(tenant, subject);
} catch (error) {
const appEmail = await SeistoreFactory.build(
Config.CLOUDPROVIDER).getEmailFromTokenPayload(req.headers.authorization, false);
const appEmail = Utils.getPropertyFromTokenPayload(req.headers.authorization,
Config.USER_ID_CLAIM_FOR_ENTITLEMENTS_SVC);
try {
await Auth.isAppAuthorized(tenant, appEmail);
} catch (error) {
......@@ -179,7 +179,7 @@ export class ImpersonationTokenHandler {
if (appEmailV2 !== appEmail) {
await Auth.isAppAuthorized(tenant, appEmailV2);
} else {
throw(error);
throw (error);
}
}
}
......
......@@ -20,7 +20,8 @@ import { SubprojectAuth, SubProjectModel } from '.';
import { Auth, AuthGroups, AuthRoles, UserRoles } from '../../auth';
import { Config, JournalFactoryTenantClient, LoggerFactory, StorageFactory } from '../../cloud';
import { SeistoreFactory } from '../../cloud/seistore';
import { DESUserAssociation, DESUtils } from '../../dataecosystem';
import { DESUtils } from '../../dataecosystem';
import { UserAssocationServiceFactory } from '../../dataecosystem/user-association';
import { Error, Feature, FeatureFlags, Response, Utils } from '../../shared';
import { DatasetDAO, PaginationModel } from '../dataset';
import { TenantAuth, TenantModel } from '../tenant';
......@@ -90,10 +91,8 @@ export class SubProjectHandler {
// Parse input parameters
const subproject = await SubProjectParser.create(req);
const userToken = req.headers.authorization;
const userEmail = await SeistoreFactory.build(
Config.CLOUDPROVIDER).getEmailFromTokenPayload(req.headers.authorization, true);
// enforce the datasets schema by key for newly create subproject.
// enforce the datasets schema by key for newly create subproject
// this will mainly affect google for which the initial implementation
// of the journal was query-based (lack in performance)
// other cloud providers already implement ref by key.
......@@ -154,22 +153,19 @@ export class SubProjectHandler {
subproject.gcs_bucket,
subproject.storage_location, subproject.storage_class);
const subprojectCreatorEmail = subproject.admin || userEmail;
subproject.admin = Utils.getSubIDFromPayload(req.headers.authorization) ||
Utils.getSubFromPayload(req.headers.authorization) || undefined;
// Register the subproject