Skip to content

Instantly share code, notes, and snippets.

@DinoChiesa
Last active January 28, 2021 00:32
Show Gist options
  • Save DinoChiesa/fc8bd7c40cfd4d6e5d1b9aa1f82acb81 to your computer and use it in GitHub Desktop.
Save DinoChiesa/fc8bd7c40cfd4d6e5d1b9aa1f82acb81 to your computer and use it in GitHub Desktop.
gcloud commands for interacting with Apigee, and also nodejs code to sign a JWT, for use in a request-for-token sent to Google APIs
(First create a service account and create+download a keyfile for it)
KEY_FILE=~/Downloads/name-of-the-downloaded-keyfile.json
(download and install gcloud if you don't have it)
gcloud components update
gcloud auth list
gcloud auth activate-service-account --key-file ${KEY_FILE}
gcloud auth list
PROJECT=my-gcp-project
gcloud config set project $PROJECT
gcloud projects list
gcloud auth print-access-token
TOKEN=output...from...above
curl https://apigee.googleapis.com/v1/organizations/$ORG/apis \
-H "Authorization: Bearer $TOKEN"
gcloud alpha apigee apis list
// signForGoogleapis.js
// ------------------------------------------------------------------
const { JWS, JWK } = require('node-jose');
const fs = require('fs');
const args = process.argv.slice(2);
const help = () => {
console.log('usage:\n node ./signForGoogleapis.js --keyjson FILENAME\n');
process.exit(1);
};
(async () => {
let wantedKeyType = null;
let keyfile = null;
args.forEach( arg => {
switch (arg) {
case '-h' :
case '--help' :
help();
break;
case '--keyjson' :
wantedKeyType = 'keyjson';
break;
default:
if (wantedKeyType == 'keyjson') {
keyfile = arg;
}
else throw new Error('unrecognized argument.');
break;
}
});
if ( ! keyfile) {
help();
}
const keyjson = fs.readFileSync(keyfile);
const json = JSON.parse(keyjson);
if ( ! json.private_key || json.type != 'service_account') {
throw new Error('that does not appear to be a googleapis service account key');
}
// create a private EC key
const signingKey = await JWK.asKey(json.private_key, "pem");
const now = Math.floor((new Date()).valueOf() / 1000);
const lifetime = 180; // seconds
const payload = {
iss: json.client_email,
scope: 'https://www.googleapis.com/auth/cloud-platform',
aud: json.token_uri,
exp: now + lifetime,
iat: now
};
const header = {
alg : 'RS256',
typ : 'JWT'
};
let signOptions = {
alg: header.alg,
fields: header,
format: 'compact'
};
// use reference:false to omit the kid from the header
let signedJwt = await JWS.createSign(signOptions, [{key:signingKey, reference:false}])
.update(JSON.stringify(payload), "utf8")
.final();
console.log(signedJwt);
console.log();
console.log(JSON.stringify(header, null, 2));
console.log(JSON.stringify(payload, null, 2));
})().catch((err) => {
console.error(err);
process.exitCode = 1;
});
{
"name": "node-jose-tools",
"version": "1.0.0",
"description": "tools for signing JWT, relying on node-jose",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "[email protected]",
"license": "Apache-2.0",
"devDependencies": {},
"dependencies": {
"node-jose": "^2.0.0"
}
}
JWT=output.from.the.signForGoogleApis.script
curl --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \
--data-urlencode "assertion=$JWT" \
https://oauth2.googleapis.com/token
ATOKEN=token.response.from.the.curl.command
curl https://apigee.googleapis.com/v1/organizations/$ORG/apis \
-H "Authorization: Bearer $ATOKEN"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment