forked from mhmdksh/vault-secret-injector
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js.bck2
175 lines (143 loc) · 5.98 KB
/
index.js.bck2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
const vault = require('node-vault');
const fs = require('fs');
const path = require('path');
// Load environment variables from a .env file if needed
require('dotenv').config();
// File path to store the last known secret values
const cacheFilePath = path.resolve(__dirname, '.last.cache.json');
const secretsFilePath = process.env.SECRETS_FILE_PATH || path.resolve('/secrets', 'secrets.env');
// Create a Vault client
const vaultClient = vault({
apiVersion: 'v1',
endpoint: process.env.VAULT_ENDPOINT,
token: process.env.VAULT_TOKEN,
});
// Function to read the secret from Vault
async function readSecret() {
const kvStore = process.env.VAULT_KV_STORE;
const secretPath = process.env.VAULT_SECRET_PATH;
try {
// Read the secret from the specified path
const secret = await vaultClient.read(`${kvStore}/data/${secretPath}`);
const secretData = secret.data.data;
// Cache the latest known secret values
fs.writeFileSync(cacheFilePath, JSON.stringify(secretData, null, 2));
console.log('Secrets cached successfully.');
// Output the values in the specified format
for (const [key, value] of Object.entries(secretData)) {
console.log(`${key}=${value}`);
}
// Write the secrets to the .env file
writeSecretsToFile(secretData);
} catch (err) {
if (err.message.includes('permission denied') || err.message.includes('invalid token')) {
console.error('Authentication Failure');
// Check if there is a cached secret available
if (fs.existsSync(cacheFilePath)) {
const cachedData = JSON.parse(fs.readFileSync(cacheFilePath, 'utf-8'));
// Output the cached values in the specified format
for (const [key, value] of Object.entries(cachedData)) {
console.log(`${key}=${value}`);
}
// Write the cached secrets to the .env file
writeSecretsToFile(cachedData);
} else {
console.error('No cached secret values available');
}
} else {
console.error('Error reading secret:', err.message);
}
}
}
// Function to write secrets to a .env file
function writeSecretsToFile(secretData) {
const secretLines = Object.entries(secretData).map(([key, value]) => `${key}=${value}`).join('\n');
// Create the .env file if it doesn't exist and log the action
if (!fs.existsSync(secretsFilePath)) {
fs.writeFileSync(secretsFilePath, '');
console.log(`Created new secrets file at ${secretsFilePath}`);
}
// Write to the .env file and log the action
fs.writeFileSync(secretsFilePath, secretLines);
console.log(`Secrets written to ${secretsFilePath}`);
}
// Function to check and renew the Vault token if it is close to expiration
async function checkToken() {
const threshold = parseInt(process.env.TOKEN_RENEW_THRESHOLD || '60', 10); // Default threshold is 60 seconds
try {
// Lookup the current token's TTL (Time to Live)
const tokenInfo = await vaultClient.tokenLookupSelf();
const ttl = tokenInfo.data.ttl; // TTL is in seconds
console.log(`Token TTL: ${ttl} seconds`);
// Check if the TTL is below the threshold
if (ttl <= threshold) {
console.log(`Token TTL is below the threshold of ${threshold} seconds. Renewing the token...`);
// Renew the token
const renewedToken = await vaultClient.tokenRenewSelf();
console.log(`Token renewed successfully. New TTL: ${renewedToken.auth.lease_duration} seconds`);
// Update the token in the Vault client
vaultClient.token = renewedToken.auth.client_token;
} else {
console.log('Token is still valid and does not need renewal.');
}
} catch (err) {
console.error('Error checking token:', err.message);
}
}
// Function to periodically check for secret updates
async function checkForUpdates() {
const kvStore = process.env.VAULT_KV_STORE;
const secretPath = process.env.VAULT_SECRET_PATH;
try {
// Read the secret from the specified path
const secret = await vaultClient.read(`${kvStore}/data/${secretPath}`);
const secretData = secret.data.data;
// Check if there are changes in the secret values
if (fs.existsSync(cacheFilePath)) {
const cachedData = JSON.parse(fs.readFileSync(cacheFilePath, 'utf-8'));
if (JSON.stringify(cachedData) !== JSON.stringify(secretData)) {
console.log('Secret values have changed.');
// Update the cache with the latest known secret values
fs.writeFileSync(cacheFilePath, JSON.stringify(secretData, null, 2));
console.log('Secrets cache updated.');
// Output the updated values in the specified format
for (const [key, value] of Object.entries(secretData)) {
console.log(`${key}=${value}`);
}
// Write the updated secrets to the .env file
writeSecretsToFile(secretData);
} else {
console.log('No changes detected in secret values.');
}
} else {
// Cache the latest known secret values if not already cached
fs.writeFileSync(cacheFilePath, JSON.stringify(secretData, null, 2));
console.log('Secrets cached for the first time.');
// Output the values in the specified format
for (const [key, value] of Object.entries(secretData)) {
console.log(`${key}=${value}`);
}
// Write the secrets to the .env file
writeSecretsToFile(secretData);
}
} catch (err) {
console.error('Error checking for updates:', err.message);
}
}
// Function to periodically check the token and secrets
function keepAlive() {
const secretsCheckInterval = parseInt(process.env.SECRETS_CHECK_INTERVAL || '5', 10); // Default to 5 seconds
const tokenCheckInterval = parseInt(process.env.TOKEN_CHECK_INTERVAL || '60', 10); // Default to 60 seconds
// Set interval to check for secrets updates
setInterval(() => {
checkForUpdates();
}, secretsCheckInterval * 1000);
// Set interval to check and renew the token
setInterval(() => {
checkToken();
}, tokenCheckInterval * 1000);
}
// Execute the readSecret function initially
readSecret().then(() => {
keepAlive();
});