berlioz
Version:
Berlioz - cloud deployment and migration services
222 lines (205 loc) • 7.33 kB
JavaScript
module.exports = (section, logger, {Promise, _, helper, gcp, deployment, cluster, region}) => {
section
.priority(1000)
.onQueryAll(() => {
var metaNames = helper.nativeProcessor.getPolicyHandlerNames();
logger.info("[GCP-POLICY] ", metaNames);
return Promise.serial(metaNames, x => queryAllFromKind(x))
.then(results => {
return _.flatten(results);
});
})
.onExtractNaming(obj => [
obj.target
])
.onExtractId(obj => obj.id)
.onQuery(id => queryFromTarget(id))
.onExtractConfig(obj => {
return {
kind: obj.kind,
policy: obj.policy
}
})
.onExtractRelations(item => {
item.relation(item.naming[0]);
for(var dn of _.keys(item.obj.relations)) {
var email = item.obj.relations[dn];
var serviceAccount = helper.getServiceAccountItem(email)
if (serviceAccount) {
item.relation(serviceAccount.dn);
}
}
})
.onAutoConfig((item, action) => {
if (action == 'delete') {
return true;
}
for(var relation of item.findRelations('gcp-sql'))
{
var sql = relation.targetItem;
if (sql) {
if (!setupSqlServiceAccount(item, sql)) {
return false;
}
}
}
return true;
})
.onCreate(delta => {
return applyPolicy(delta)
})
.onUpdate(delta => {
return applyPolicy(delta)
})
.onDelete(delta => {
})
;
function queryAllFromKind(kind)
{
var targets = helper._currentConfig.section(kind).items;
return Promise.serial(targets, target => queryFromTarget(target))
.then(result => {
return result.filter(x => x);
});
}
function queryFromTarget(target)
{
logger.info('[queryAllFromTarget] %s :: %s -> %s...', target.meta.name, target.dn, target.id);
var queryCb = helper.nativeProcessor.getPolicyHandler(target.meta.name).query;
if (!queryCb) {
return null;
}
return queryCb(target.id)
.then(policy => {
if (!policy) {
return null;
}
var massagedPolicy = {
}
var relations = {
}
for(var x of policy) {
for(var member of x.members) {
var i = member.indexOf(':')
var memberType = member.substring(0, i);
var memberId = member.substring(i + 1);
if (memberType == 'serviceAccount') {
var serviceAccount = helper.getServiceAccountItem(memberId)
if (serviceAccount) {
addToPolicy(massagedPolicy, x.role, 'relation', memberType, serviceAccount.dn);
relations[serviceAccount.dn] = memberId;
} else {
addToPolicy(massagedPolicy, x.role, 'id', memberType, memberId);
}
} else {
addToPolicy(massagedPolicy, x.role, 'id', memberType, memberId);
}
}
}
return {
id: {
id: target.id,
dn: target.dn,
meta: {
name: target.meta.name
}
},
target: target.dn,
kind: target.meta.name,
policy: massagedPolicy,
relations: relations
}
});
}
function addToPolicy(policy, role, folder, memberType, memberId)
{
if (!policy[role]) {
policy[role] = {
id: {},
relation: {}
}
}
if (!policy[role][folder][memberType]) {
policy[role][folder][memberType] = {}
}
policy[role][folder][memberType][memberId] = true;
}
function getBody(obj)
{
var result = []
for(var role of _.keys(obj)) {
var roleResult = getRoleBody(role, obj[role]);
if (roleResult) {
result.push(roleResult);
}
}
return result;
}
function getRoleBody(role, obj)
{
var result = {
role: role,
members: []
}
for(var memberKind of _.keys(obj.id)) {
for(var memberId of _.keys(obj.id[memberKind])) {
var member = memberKind + ':' + memberId;
result.members.push(member);
}
}
for(var memberKind of _.keys(obj.relation)) {
for(var targetDn of _.keys(obj.relation[memberKind])) {
var target = helper._currentConfig.findDn(targetDn);
if (target) {
// TODO: make this generic
var member = memberKind + ':' + target.obj.email;
result.members.push(member);
}
}
}
if (result.members.length == 0) {
return null;
}
return result;
}
function applyPolicy(delta)
{
logger.info('[applyPolicy] %s...', delta.dn);
var policyBody = getBody(delta.config.policy);
logger.info('[applyPolicy] %s, policyBody: ', delta.dn, policyBody);
var target = helper._currentConfig.findDn(delta.naming[0]);
if (!target) {
logger.warn('[applyPolicy] %s. target is missing.', delta.dn);
return;
}
if (!target.id) {
logger.warn('[applyPolicy] %s. target is not present.', delta.dn);
return;
}
var applyCb = helper.nativeProcessor.getPolicyHandler(target.meta.name).apply;
if (!applyCb) {
logger.warn('[applyPolicy] %s. apply cb not present.', delta.dn);
return null;
}
logger.info('[applyPolicy] %s. applying...', delta.dn, policyBody);
return applyCb(target.id, policyBody)
.then(() => {
return queryFromTarget(target);
});
}
function setupSqlServiceAccount(item, sql)
{
if (!sql.obj) {
helper.postponeWithTimeout(1 * 60, `SQL ${sql.dn} is not yet ready`);
return false;
}
var serviceAccount = sql.obj.serviceAccountEmailAddress;
if (!serviceAccount) {
helper.postponeWithTimeout(1 * 60, `SQL Service Account not present for ${sql.dn}`);
return false;
}
var role = 'roles/storage.objectViewer';
addToPolicy(item.config.policy, role, 'id', 'serviceAccount', serviceAccount);
return true;
}
}