Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active May 20, 2024 12:10
Show Gist options
  • Save salrashid123/ac54c655b8f8ef1e3da84d71f510c9cd to your computer and use it in GitHub Desktop.
Save salrashid123/ac54c655b8f8ef1e3da84d71f510c9cd to your computer and use it in GitHub Desktop.
Impersonated Credentials for GCP node.js
const gaxios = require('gaxios');
const { GoogleAuth, JWT, Impersonated, ImpersonatedOptions } = require('google-auth-library');
const { Storage } = require('@google-cloud/storage');
const { SecretManagerServiceClient } = require('@google-cloud/secret-manager');
// node -e 'require("./main").demo()'
// tsc -d -p /home/srashid/Desktop/node_impersonated/google-auth-library-nodejs/tsconfig.json
// cp -R /home/srashid/Desktop/node_impersonated/google-auth-library-nodejs/build/src/* node_modules/google-auth-library/build/src/
const demo = module.exports.demo = async function () {
var svcAccountFile = '/home/srashid/gcp_misc/certs/mineral-minutia-820-e9a7c8665867.json';
var project_id = 'fabled-ray-104117';
const keys = require(svcAccountFile);
// create a sourceCredential
let saclient = new JWT(
keys.client_email,
null,
keys.private_key,
['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/iam'],
);
// Use that to impersonate the targetPrincipal
let targetClient = new Impersonated({
sourceClient: saclient,
targetPrincipal: "impersonated-account@fabled-ray-104117.iam.gserviceaccount.com",
lifetime: 30,
delegates: [],
targetScopes: ["https://www.googleapis.com/auth/cloud-platform"]
});
// At this point you can use the client as any other:
// 1. Acquire Headers
const authHeaders = await targetClient.getRequestHeaders();
console.log(authHeaders);
// 2. Use client in authorized session
await targetClient.getAccessToken().then(res => {
let url = 'https://www.googleapis.com/storage/v1/b?project=' + project_id
targetClient.requestAsync({ url }).then(resp => {
console.log(resp.data.items[0]);
}).catch(function (error) {
console.error('Unable to list buckets: ' + error);
});
});
// 3. Use client with GCP Service
// SecretManager
var AuthClient = function (client) {
this._client = client;
};
AuthClient.prototype.getClient = function () {
return this._client;
};
var ac = new AuthClient(targetClient);
const sm_client = new SecretManagerServiceClient({
projectId: project_id,
auth: ac,
});
const secret_name = 'projects/248066739582/secrets/secret1/versions/1';
const [accessResponse] = await sm_client.accessSecretVersion({
name: secret_name,
});
const responsePayload = accessResponse.payload.data.toString('utf8');
console.info(`Payload: ${responsePayload}`);
// Storage
const storage = new Storage( { projectId: project_id, auth: ac } );
async function listBuckets() {
const [buckets] = await storage.getBuckets();
console.log('Buckets:');
buckets.forEach(bucket => {
console.log(bucket.name);
});
}
await listBuckets().catch(console.error);
//////////////////////////////////////////////////////////////
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
const { DownscopedClient } = require('google-auth-library');
const auth = new GoogleAuth({
keyFilename: svcAccountFile,
scopes: 'https://www.googleapis.com/auth/cloud-platform',
});
const testAvailableResource = '//storage.googleapis.com/projects/_/buckets/mineral-minutia-820-cab1';
const testAvailablePermission1 = 'inRole:roles/storage.objectViewer';
const testAvailabilityConditionExpression = "resource.name.startsWith('projects/_/buckets/mineral-minutia-820-cab1/objects/foo')";
const cabWithEmptyAccessBoundaryRules = {
accessBoundary: {
accessBoundaryRules: [
{
availableResource: testAvailableResource,
availablePermissions: [testAvailablePermission1],
availabilityCondition: {
expression: testAvailabilityConditionExpression,
},
},
],
},
};
const client = await auth.getClient();
let dc = new DownscopedClient(client, cabWithEmptyAccessBoundaryRules);
dc.getAccessToken().then(res => {
//console.log(res.token);
gaxios.request({url: 'https://storage.googleapis.com/storage/v1/b/mineral-minutia-820-cab1/o/foo.txt?alt=media',
headers: { 'Authorization': 'Bearer ' + res.token }}).then(resp => {
console.log(resp.data);
}).catch(function (error) {
console.error('Unable to get object: ' + error);
});
}, err => {console.log(err);});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment