This repository has been archived by the owner on Jul 26, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 404
/
kv-backend.js
117 lines (102 loc) · 3.85 KB
/
kv-backend.js
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
'use strict'
const AbstractBackend = require('./abstract-backend')
/** Key Value backend class. */
class KVBackend extends AbstractBackend {
/**
* Create a Key Value backend.
* @param {Object} logger - Logger for logging stuff.
*/
constructor ({ logger }) {
super()
this._logger = logger
}
/**
* Fetch Kubernetes secret property values.
* @param {Object[]} data - Kubernetes secret properties.
* @param {string} data[].key - Secret key in the backend.
* @param {string} data[].name - Kubernetes Secret property name.
* @param {string} data[].property - If the backend secret is an
* object, this is the property name of the value to use.
* @param {string} roleArn - If the client should assume a role before fetching the secret
* @returns {Promise} Promise object representing secret property values.
*/
_fetchDataValues ({ data, roleArn }) {
return Promise.all(data.map(async secretProperty => {
this._logger.info(`fetching secret property ${secretProperty.name} with role: ${roleArn || 'no role set'}`)
const plainOrObjValue = await this._get({ secretKey: secretProperty.key, roleArn })
const shouldParseValue = 'property' in secretProperty
let value = plainOrObjValue
if (shouldParseValue) {
let parsedValue
try {
parsedValue = JSON.parse(value)
} catch (err) {
this._logger.warn(`Failed to JSON.parse value for '${secretProperty.key}',` +
` please verify that your secret value is correctly formatted as JSON.` +
` To use plain text secret remove the 'property: ${secretProperty.property}'`)
return
}
if (!(secretProperty.property in parsedValue)) {
throw new Error(`Could not find property ${secretProperty.property} in ${secretProperty.key}`)
}
value = parsedValue[secretProperty.property]
}
return { [secretProperty.name]: value }
}))
}
/**
* Fetch Kubernetes secret property values.
* @param {string[]} dataFrom - Array of secret keys in the backend
* @param {string} roleArn - If the client should assume a role before fetching the secret
* @returns {Promise} Promise object representing secret property values.
*/
_fetchDataFromValues ({ dataFrom, roleArn }) {
return Promise.all(dataFrom.map(async secretKey => {
this._logger.info(`fetching secret ${secretKey} with role: ${roleArn || 'no role set'}`)
const value = await this._get({ secretKey, roleArn })
try {
return JSON.parse(value)
} catch (err) {
this._logger.warn(`Failed to JSON.parse value for '${secretKey}',` +
` please verify that your secret value is correctly formatted as JSON.`)
}
}))
}
/**
* Get a secret property value from Key Value backend.
*/
_get () {
throw new Error('_get not implemented')
}
/**
* Fetch Kubernetes secret manifest data.
* @param {SecretDescriptor} secretDescriptor - Kubernetes secret descriptor.
* @returns {Promise} Promise object representing Kubernetes secret manifest data.
*/
async getSecretManifestData ({
secretDescriptor: {
// Use secretDescriptor.properties to be backwards compatible.
properties = [],
data = properties,
dataFrom = [],
roleArn
}
}) {
const [dataFromValues, dataValues] = await Promise.all([
this._fetchDataFromValues({ dataFrom, roleArn }),
this._fetchDataValues({ data, roleArn })
])
const plainValues = dataFromValues.concat(dataValues)
.reduce((acc, parsedValue) => ({
...acc,
...parsedValue
}), {})
const encodedEntries = Object.entries(plainValues)
.map(([name, plainValue]) => [
name,
(Buffer.from(`${plainValue}`, 'utf8')).toString('base64')
])
return Object.fromEntries(encodedEntries)
}
}
module.exports = KVBackend