google-cloud-secrets-manager
Advanced tools
Comparing version 1.0.1 to 1.0.2
{ | ||
"name": "google-cloud-secrets-manager", | ||
"version": "1.0.1", | ||
"description": "Google Cloud Secrets Manager Operator", | ||
"main": "src/index.ts", | ||
"scripts": { | ||
"start": "node src/index.ts" | ||
}, | ||
"author": "", | ||
"license": "Apache-2.0", | ||
"dependencies": { | ||
"dotenv": "^16.3.1" | ||
}, | ||
"compilerOptions": { | ||
"outDir": "./dist", | ||
"rootDir": "./src", | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
"exclude": [ | ||
"node_modules" | ||
] | ||
}, | ||
"devDependencies": { | ||
"@types/node": "18.17.9", | ||
"ts-node": "^10.9.1" | ||
} | ||
"name": "google-cloud-secrets-manager", | ||
"version": "1.0.2", | ||
"description": "Google Cloud Secrets Manager Operator", | ||
"main": "src/index.ts", | ||
"scripts": { | ||
"start": "node src/index.ts", | ||
"build": "tsc" | ||
}, | ||
"author": "", | ||
"license": "Apache-2.0", | ||
"dependencies": { | ||
"dotenv": "^16.3.1" | ||
}, | ||
"compilerOptions": { | ||
"outDir": "./dist", | ||
"rootDir": "./src", | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
"exclude": [ | ||
"node_modules" | ||
] | ||
}, | ||
"devDependencies": { | ||
"@types/node": "18.17.9", | ||
"ts-node": "^10.9.1" | ||
} | ||
} |
@@ -1,11 +0,1 @@ | ||
import { SecretsStore } from "./SecretsStore"; | ||
import dotenv from 'dotenv'; | ||
dotenv.config(); | ||
getSecret("hola") | ||
async function getSecret(secret : string) : Promise<string | null>{ | ||
const secretsStore = new SecretsStore(); | ||
var promise = secretsStore.retrieveCredential(secret); | ||
return await promise | ||
} | ||
export { SecretsStore } from './SecretsStore'; |
// Code taken from https://gist.github.com/markelliot/6627143be1fc8209c9662c504d0ff205 and modified | ||
import crypto from 'crypto'; | ||
import { getEnvironment } from '../util/environment' | ||
@@ -54,9 +53,13 @@ function objectToBase64url(object: object) { | ||
* | ||
* @param {string} user the service user identity, typically of the | ||
* form [user]@[project].iam.gserviceaccount.com | ||
* @param {string} key the private key corresponding to user | ||
* @param {string} scope the scopes to request for this token, a | ||
* listing of available scopes is provided at | ||
* https://developers.google.com/identity/protocols/oauth2/scopes | ||
* @returns a valid Google auth token for the provided service user and scope or undefined | ||
*/ | ||
export async function getGoogleAuthToken(): Promise<string> { | ||
export async function getGoogleAuthToken(user: string, key: string): Promise<string> { | ||
const jwtHeader = objectToBase64url({alg: 'RS256', typ: 'JWT'}); | ||
try { | ||
const {user, key} = getEnvironment(); | ||
const assertion_time = Math.round(Date.now() / 1000); | ||
@@ -73,3 +76,3 @@ const expiry_time = assertion_time + 3600; | ||
const jwtUnsigned = jwtHeader + '.' + claim_set; | ||
const signedJwt = jwtUnsigned + '.' + (await sign(jwtUnsigned, key as string)); | ||
const signedJwt = jwtUnsigned + '.' + (await sign(jwtUnsigned, key)); | ||
const body = 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=' + signedJwt; | ||
@@ -76,0 +79,0 @@ const response = await fetch('https://oauth2.googleapis.com/token', { |
@@ -1,113 +0,115 @@ | ||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference | ||
///<reference path="types/global-node.d.ts"/> | ||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference | ||
///<reference path="types/global-variables.d.ts"/> | ||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference | ||
///<reference path="types/global-deno.d.ts"/> | ||
import { getGoogleAuthToken } from './infrastructure/gcsm'; | ||
import { IAddSecretVersionRequest, ISecret } from './domain/gcsm'; | ||
import { ISecretHandle, LabelAlias } from './domain/secrets'; | ||
import { getEnvironment } from './util/environment' | ||
export class SecretsStore { | ||
private readonly GCP_SECRETS_MANAGER_BASE_URL_V1 = 'https://secretmanager.googleapis.com/v1'; | ||
private readonly GCP_SECRETS_MANAGER_BASE_URL_V1 = 'https://secretmanager.googleapis.com/v1'; | ||
/** | ||
* Encrypts and stores the {@param credential}. Uses {@param labels} as labels of the secret. | ||
* @param secretId | ||
* @param credential | ||
* @param labels | ||
* | ||
* @returns string identifying the secret. | ||
*/ | ||
storeCredential = async (secretId: string, credential: string, labels: LabelAlias): Promise<string | null | undefined> => { | ||
const token = await getGoogleAuthToken(); | ||
// 1. create secret. Creating a secret does not insert its payload. | ||
const createdSecret = await this.createSecret(secretId, token, labels); | ||
if (createdSecret.name != null) { | ||
// 2. add version to that secret | ||
await this.createSecretVersion(credential, createdSecret.internal_name, token); | ||
return createdSecret.internal_name; | ||
} | ||
return null; | ||
}; | ||
private readonly user: string; | ||
retrieveCredential = async (credentialRef: string): Promise<string | null> => { | ||
const token = await getGoogleAuthToken(); | ||
return await this.retrieveSecret(credentialRef, token); | ||
}; | ||
private readonly key: string; | ||
updateCredential = async (credentialRef: string, newCredential: string) => { | ||
const token = await getGoogleAuthToken(); | ||
const currentCredentialValue = await this.retrieveSecret(credentialRef, token); | ||
if (newCredential != currentCredentialValue) { | ||
return await this.createSecretVersion(newCredential, credentialRef, token); | ||
} | ||
return null; | ||
}; | ||
private readonly project_name: string; | ||
private async retrieveSecret(credentialRef: string, token: string): Promise<string | null> { | ||
const {project_name} = getEnvironment(); | ||
const accessLastSecretVersionResponse = await fetch(`${this.GCP_SECRETS_MANAGER_BASE_URL_V1}/projects/${project_name}/secrets/${credentialRef}/versions/latest:access`, { | ||
headers: { | ||
Authorization: `Bearer ${token}` | ||
} | ||
}); | ||
const accessLastSecretVersionResponseBody = await accessLastSecretVersionResponse.json(); | ||
if (typeof accessLastSecretVersionResponseBody?.payload?.data == 'string') { | ||
return atob(accessLastSecretVersionResponseBody.payload.data); | ||
} else { | ||
return null; | ||
constructor({user, key, project_name}: { user: string, key: string, project_name: string }) { | ||
this.user = user; | ||
this.key = key; | ||
this.project_name = project_name; | ||
} | ||
} | ||
private async createSecretVersion(credential: string, secretRef: string, token: string) { | ||
const {project_name} = getEnvironment(); | ||
const createSecretVersionRequest: IAddSecretVersionRequest = { | ||
payload: { | ||
data: btoa(credential) | ||
} | ||
/** | ||
* Encrypts and stores the {@param credential}. Uses {@param labels} as labels of the secret. | ||
* @param secretId | ||
* @param credential | ||
* @param labels | ||
* | ||
* @returns string identifying the secret. | ||
*/ | ||
storeCredential = async (secretId: string, credential: string, labels: LabelAlias): Promise<string | null | undefined> => { | ||
const token = await getGoogleAuthToken(this.user, this.key); | ||
// 1. create secret. Creating a secret does not insert its payload. | ||
const createdSecret = await this.createSecret(secretId, token, labels); | ||
if (createdSecret.name != null) { | ||
// 2. add version to that secret | ||
await this.createSecretVersion(credential, createdSecret.internal_name, token); | ||
return createdSecret.internal_name; | ||
} | ||
return null; | ||
}; | ||
const createSecretVersionResponse = await fetch(`${this.GCP_SECRETS_MANAGER_BASE_URL_V1}/projects/${project_name}/secrets/${secretRef}:addVersion`, { | ||
headers: { | ||
Authorization: `Bearer ${token}` | ||
}, | ||
method: 'POST', | ||
body: JSON.stringify(createSecretVersionRequest) | ||
}); | ||
const createdSecretVersionResponseBody = await createSecretVersionResponse.json(); | ||
console.log(`New secret version created for secret ${secretRef} with name: ${createdSecretVersionResponseBody.name}`); | ||
return createdSecretVersionResponseBody; | ||
} | ||
private async createSecret(secretId: string, token: string, labels: LabelAlias): Promise<ISecretHandle> { | ||
const secret: ISecret = { | ||
replication: { | ||
automatic: { | ||
customerManagedEncryption: null | ||
retrieveCredential = async (credentialRef: string): Promise<string | null> => { | ||
const token = await getGoogleAuthToken(this.user, this.key); | ||
return await this.retrieveSecret(credentialRef, token); | ||
}; | ||
updateCredential = async (credentialRef: string, newCredential: string) => { | ||
const token = await getGoogleAuthToken(this.user, this.key); | ||
const currentCredentialValue = await this.retrieveSecret(credentialRef, token); | ||
if (newCredential != currentCredentialValue) { | ||
return await this.createSecretVersion(newCredential, credentialRef, token); | ||
} | ||
}, | ||
labels: labels | ||
return null; | ||
}; | ||
const urlSearchParams = new URLSearchParams({ | ||
secretId: secretId | ||
}); | ||
private async retrieveSecret(credentialRef: string, token: string): Promise<string | null> { | ||
const accessLastSecretVersionResponse = await fetch(`${this.GCP_SECRETS_MANAGER_BASE_URL_V1}/projects/${this.project_name}/secrets/${credentialRef}/versions/latest:access`, { | ||
headers: { | ||
Authorization: `Bearer ${token}` | ||
} | ||
}); | ||
const accessLastSecretVersionResponseBody = await accessLastSecretVersionResponse.json(); | ||
if (typeof accessLastSecretVersionResponseBody?.payload?.data == 'string') { | ||
return atob(accessLastSecretVersionResponseBody.payload.data); | ||
} else { | ||
return null; | ||
} | ||
} | ||
const {project_name} = getEnvironment(); | ||
const createSecretResponse = await fetch(`${this.GCP_SECRETS_MANAGER_BASE_URL_V1}/projects/${project_name}/secrets?` + urlSearchParams, { | ||
headers: { | ||
Authorization: `Bearer ${token}` | ||
}, | ||
method: 'POST', | ||
body: JSON.stringify(secret) | ||
}); | ||
const created_secret = await createSecretResponse.json(); | ||
console.log(`Secret created with name: ${created_secret.name} and labels ${JSON.stringify(created_secret.labels)}`); | ||
return created_secret; | ||
} | ||
private async createSecretVersion(credential: string, secretRef: string, token: string) { | ||
const createSecretVersionRequest: IAddSecretVersionRequest = { | ||
payload: { | ||
data: btoa(credential) | ||
} | ||
}; | ||
const createSecretVersionResponse = await fetch(`${this.GCP_SECRETS_MANAGER_BASE_URL_V1}/projects/${this.project_name}/secrets/${secretRef}:addVersion`, { | ||
headers: { | ||
Authorization: `Bearer ${token}` | ||
}, | ||
method: 'POST', | ||
body: JSON.stringify(createSecretVersionRequest) | ||
}); | ||
const createdSecretVersionResponseBody = await createSecretVersionResponse.json(); | ||
console.log(`New secret version created for secret ${secretRef} with name: ${createdSecretVersionResponseBody.name}`); | ||
return createdSecretVersionResponseBody; | ||
} | ||
private async createSecret(secretId: string, token: string, labels: LabelAlias): Promise<ISecretHandle> { | ||
const secret: ISecret = { | ||
replication: { | ||
automatic: { | ||
customerManagedEncryption: null | ||
} | ||
}, | ||
labels: labels | ||
}; | ||
const urlSearchParams = new URLSearchParams({ | ||
secretId: secretId | ||
}); | ||
const createSecretResponse = await fetch(`${this.GCP_SECRETS_MANAGER_BASE_URL_V1}/projects/${this.project_name}/secrets?` + urlSearchParams, { | ||
headers: { | ||
Authorization: `Bearer ${token}` | ||
}, | ||
method: 'POST', | ||
body: JSON.stringify(secret) | ||
}); | ||
const created_secret = await createSecretResponse.json(); | ||
console.log(`Secret created with name: ${created_secret.name} and labels ${JSON.stringify(created_secret.labels)}`); | ||
return { | ||
internal_name: secretId, | ||
...created_secret | ||
} as ISecretHandle; | ||
} | ||
} | ||
{ | ||
"compilerOptions": { | ||
"lib": ["ES2018", "dom"], | ||
"lib": ["ES2022", "dom"], | ||
"module": "CommonJS", | ||
"target": "ES2018", | ||
"target": "ES2022", | ||
"outDir": "./dist", | ||
@@ -17,2 +17,2 @@ "rootDir": "./src", | ||
] | ||
} | ||
} |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
AI-detected possible typosquat
Supply chain riskAI has identified this package as a potential typosquat of a more popular package. This suggests that the package may be intentionally mimicking another package's name, description, or other metadata.
Found 1 instance in 1 package
24118
549
12
4