Commit 93da0fc3 authored by Shrikant Garg's avatar Shrikant Garg
Browse files

Merge branch 'IBM-credentail-changes' into 'master'

Ibm credentail changes

See merge request !77
parents ae11cbba 0d960ba4
Pipeline #39644 passed with stages
in 8 minutes and 43 seconds
......@@ -14,12 +14,20 @@ export class IbmConfig extends Config {
// max len for a group name in DE
public static DES_GROUP_CHAR_LIMIT = 256;
// env
public static IBM_ENVIRONMENT: string;
public static IBM_REGION: string;
// IBM COS
public static COS_ACCESS_KEY_ID: string;
public static COS_SECRET_ACCESS_KEY: string;
public static COS_ENDPOINT: string;
public static COS_S3_FORCEPATHSTYLE: boolean;
public static COS_SIGNATUREVERSION: string;
public static COS_SUBUSER_ACCESS_KEY_ID: string;
public static COS_SUBUSER_SECRET_ACCESS_KEY: string;
public static COS_TEMP_CRED_EXPITY: string;
// IBM Keycloak
public static KEYCLOAK_BASEURL: string;
......@@ -65,6 +73,9 @@ export class IbmConfig extends Config {
IbmConfig.COS_ENDPOINT = process.env.COS_ENDPOINT;
IbmConfig.COS_S3_FORCEPATHSTYLE = process.env.COS_S3_FORCEPATHSTYLE === 'true';// string to boolean
IbmConfig.COS_SIGNATUREVERSION = process.env.COS_SIGNATUREVERSION;
IbmConfig.COS_SUBUSER_ACCESS_KEY_ID = process.env.COS_SUBUSER_ACCESS_KEY_ID;
IbmConfig.COS_SUBUSER_SECRET_ACCESS_KEY = process.env.COS_SUBUSER_SECRET_ACCESS_KEY;
IbmConfig.COS_TEMP_CRED_EXPITY = process.env.COS_TEMP_CRED_EXPITY;
// IBM Keycloak
IbmConfig.KEYCLOAK_BASEURL = process.env.KEYCLOAK_BASEURL;
......
/* Licensed Materials - Property of IBM */
/* (c) Copyright IBM Corp. 2020. All Rights Reserved.*/
import { Utils } from '../../../shared';
import KcAdminClient from 'keycloak-admin';
import { AbstractCredentials, CredentialsFactory, IAccessTokenModel } from '../../credentials';
import { Config } from '../../config';
import { IbmConfig } from './config';
import { logger } from './logger';
import { IBMSTShelper } from './stshelper';
import { DatastoreDAO } from './datastore';
@CredentialsFactory.register('ibm')
export class Credentials extends AbstractCredentials {
......@@ -14,57 +20,71 @@ export class Credentials extends AbstractCredentials {
private serviceAccountAccessToken: IAccessTokenModel;
private serviceAccountAccessTokenExpiresIn = 0;
private ibmSTSHelper = new IBMSTShelper();
async getBucketFolder(tenant: string, subproject: string): Promise<string> {
const ibmDatastoreHelper = new DatastoreDAO(Config.TENANT_JOURNAL_ON_DATA_PARTITION ? {
name: tenant,
esd: tenant + '.domain.com',
default_acls: tenant,
gcpid: tenant
} : undefined);
const spkey = ibmDatastoreHelper.createKey({
namespace: Config.SEISMIC_STORE_NS + '-' + tenant,
path: [Config.SUBPROJECTS_KIND, subproject],
});
logger.debug('Printing Key', spkey)
const [spentity] = await ibmDatastoreHelper.get(spkey);
logger.debug('Printing Key', spentity.gcs_bucket)
const bucket = spentity.gcs_bucket;
return bucket;
}
public async getStorageCredentials(
tenant: string, subproject: string,
bucket: string, readonly: boolean, partitionID: string): Promise<IAccessTokenModel> {
logger.info('In Credentials.getStorageCredentials.');
const adminClient = new KcAdminClient();
adminClient.setConfig(
{
baseUrl: IbmConfig.KEYCLOAK_BASEURL,
realmName: IbmConfig.KEYCLOAK_REALM,
requestConfig: {
// `url` is the server URL that will be used for the request
url: IbmConfig.KEYCLOAK_URL_TOKEN,
// `method` is the request method to be used when making the request
method: 'post', // default
},
}
);
bucket: string, readonly: boolean, _partition: string): Promise<IAccessTokenModel> {
logger.debug(adminClient.getRequestConfig());
const crdntls = {
username: IbmConfig.KEYCLOAK_USERNAME,
password: IbmConfig.KEYCLOAK_PASSWORD,
grantType: IbmConfig.KEYCLOAK_GRANTTYPE,
clientId: IbmConfig.KEYCLOAK_CLIENTID,
clientSecret: IbmConfig.KEYCLOAK_CLIENTSECRET,
};
const expDuration = IbmConfig.COS_TEMP_CRED_EXPITY;
let roleArn = '';
let credentials = '';
logger.info('Authenticating.');
try {
await adminClient.auth(crdntls);
} catch (error) {
logger.error('Authentication failure.');
throw new Error(error);
}
let flagUpload = true;
const keypath = await this.getBucketFolder(tenant, subproject);
// this is temporary. Once dataset is being passed to get gcs token,
// this can start getting folder from gcs url along with bucket
const s3bucket = keypath;
logger.info('Getting token by calling getAccessToken.');
const token = adminClient.getAccessToken();
logger.info('Extracting token type and epiry value from token.');
const tokenType = Utils.getPropertyFromTokenPayload(token,'typ');
const tokenExpiry:number = +Utils.getPropertyFromTokenPayload(token,'exp');// converted string to number
if (readonly) { // readOnly True
roleArn = 'arn:123:456:789:1234';
flagUpload = false;
} else // readOnly False
{
roleArn = 'arn:123:456:789:1234';
flagUpload = true;
}
logger.info('Returning from Credentials.getStorageCredentials.');
return {
access_token : token,
expires_in : tokenExpiry,
token_type : tokenType,
credentials = await this.ibmSTSHelper.getCredentials(s3bucket, keypath, roleArn, flagUpload, expDuration);
const result = {
access_token: credentials,
expires_in: 7200,
token_type: 'Bearer',
};
return result;
}
public async getServiceCredentials(): Promise<string> {
logger.info('In Credentials.getServiceCredentials.');
const adminClient = new KcAdminClient();
......@@ -98,7 +118,7 @@ export class Credentials extends AbstractCredentials {
logger.info('Getting token by calling getAccessToken.');
const token = adminClient.getAccessToken();
logger.debug('Token - '+token);
logger.debug('Token - ' + token);
logger.info('Returning from Credentials.getStorageCredentials.');
return token;
}
......
import { IbmConfig } from './config';
import {STS} from 'aws-sdk';
export class IBMSTShelper{
private sts: STS;
public constructor() {
this.sts = new STS({apiVersion: '2014-11-06',
endpoint: IbmConfig.COS_ENDPOINT,
accessKeyId: IbmConfig.COS_SUBUSER_ACCESS_KEY_ID,
secretAccessKey: IbmConfig.COS_SUBUSER_SECRET_ACCESS_KEY,
region: 'us-south',});
}
public async getCredentials(bucketName: string, keypath: string,
roleArn: string, flagUpload: boolean, exp: string): Promise<string> {
let policy;
if(flagUpload === true)
policy = this.createUploadPolicy(bucketName,keypath);
else
policy = this.createDownloadPolicy(bucketName,keypath);
// hardcoded policy
// policy= '{"Version":"2012-10-17","Statement":
// [{"Sid":"Stmt1","Effect":"Allow","Action":"s3:*","Resource":"arn:aws:s3:::*"}]}' ;
const expDuration: number = +exp;
const stsParams = {
ExternalId: 'OSDUAWS',
Policy: policy,
RoleArn: roleArn,
RoleSessionName: 'OSDUAWSAssumeRoleSession',
DurationSeconds: expDuration
};
const roleCreds = await this.sts.assumeRole(stsParams).promise();
const tempCreds= roleCreds.Credentials.AccessKeyId+':'+roleCreds.Credentials.SecretAccessKey
+':'+roleCreds.Credentials.SessionToken;
return tempCreds;
}
public createUploadPolicy(bucketName: string, keypath: string): string {
const UploadPolicy = {
Version: '2012-10-17',
Statement: [
{
Sid: 'One', // Statement 1: Allow Listing files at the file location
Effect: 'Allow',
Action: [
's3:ListBucket'
],
Resource: [
'arn:aws:s3:::'+bucketName
]
},
{
Sid: 'Two', // Statement 2: Allow Listing files under the file location
Effect: 'Allow',
Action: [
's3:*'
],
Resource: [
'arn:aws:s3:::'+bucketName
]
},
{
Sid: 'Three', // Statement 3: Allow Uploading files at the file location
Effect: 'Allow',
Action: [
's3:PutObject',
's3:DeleteObject',
's3:GetObject',
's3:ListBucketMultipartUploads',
's3:AbortMultipartUpload',
's3:ListMultipartUploadParts'
],
Resource: [
'arn:aws:s3:::'+bucketName
]
},
{
Sid: 'Four', // Statement 4: Allow Uploading files under the file location
Effect: 'Allow',
Action: [
's3:PutObject',
's3:DeleteObject',
's3:GetObject',
's3:ListBucketMultipartUploads',
's3:AbortMultipartUpload',
's3:ListMultipartUploadParts'
],
Resource: [
'arn:aws:s3:::'+bucketName+'/*'
]
}
]
};
const policy = JSON.stringify(UploadPolicy);
return policy;
}
public createDownloadPolicy(bucketName: string, keypath: string): string {
const downloadPolicy = {
Version: '2012-10-17',
Statement: [
{
Sid: 'One', // Statement 1: Allow Listing files at the file location
Effect: 'Allow',
Action: [
's3:ListBucket'
],
Resource: [
'arn:aws:s3:::'+bucketName
]
},
{
Sid: 'Two', // Statement 2: Allow Listing files under the file location
Effect: 'Allow',
Action: [
's3:*'
],
Resource: [
'arn:aws:s3:::'+bucketName
]
},
{
Sid: 'Three', // Statement 3: Allow Downloading files at the file location
Effect: 'Allow',
Action: [
's3:GetObject',
's3:GetObjectVersion'
],
Resource: [
'arn:aws:s3:::'+bucketName
]
},
{
Sid: 'Four', // Statement 4: Allow Downloading files under the file location
Effect: 'Allow',
Action: [
's3:GetObject',
's3:GetObjectVersion'
],
Resource: [
'arn:aws:s3:::'+bucketName+'/*'
]
}
]
};
const policy = JSON.stringify(downloadPolicy);
return policy;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment