feat: 🎸 vault ldap cred
This commit is contained in:
1 parent
d79bd54f0b
commit
3b7873302b
8 files changed
+154
-21
No files matched your search
@@ -76,13 +76,13 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
|
||||
path;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault-generic',
|
||||
for: ['vault-generic', 'vault-ldap'],
|
||||
description: 'It indicates the type of credential the library returns.',
|
||||
})
|
||||
credential_type;
|
||||
|
||||
@attr('object-as-array', {
|
||||
for: 'vault-generic',
|
||||
for: ['vault-generic', 'vault-ldap'],
|
||||
description: 'It indicates the credential mapping overrides.',
|
||||
})
|
||||
credential_mapping_overrides;
|
||||
|
||||
@@ -38,6 +38,7 @@ export const options = {
|
||||
export const TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC = 'vault-generic';
|
||||
export const TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE =
|
||||
'vault-ssh-certificate';
|
||||
export const TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP = 'vault-ldap';
|
||||
|
||||
/**
|
||||
* Supported Credential Library types.
|
||||
@@ -45,6 +46,7 @@ export const TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE =
|
||||
export const TYPES_CREDENTIAL_LIBRARY = Object.freeze([
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
]);
|
||||
|
||||
export default class CredentialLibraryModel extends GeneratedCredentialLibraryModel {
|
||||
@@ -65,7 +67,8 @@ export default class CredentialLibraryModel extends GeneratedCredentialLibraryMo
|
||||
get isVault() {
|
||||
return (
|
||||
this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC ||
|
||||
this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE
|
||||
this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE ||
|
||||
this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP
|
||||
);
|
||||
}
|
||||
|
||||
@@ -84,4 +87,12 @@ export default class CredentialLibraryModel extends GeneratedCredentialLibraryMo
|
||||
get isVaultSSHCertificate() {
|
||||
return this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if credential is a vault ldap type.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isVaultLDAP() {
|
||||
return this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import ApplicationSerializer from './application';
|
||||
import {
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
options,
|
||||
} from '../models/credential-library';
|
||||
|
||||
@@ -29,6 +30,8 @@ export default class CredentialLibrarySerializer extends ApplicationSerializer {
|
||||
return this.serializeVaultGeneric(...arguments);
|
||||
case TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE:
|
||||
return this.serializeVaultSshCertificate(...arguments);
|
||||
case TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP:
|
||||
return this.serializeVaultLdap(...arguments);
|
||||
default:
|
||||
return super.serialize(...arguments);
|
||||
}
|
||||
@@ -44,21 +47,7 @@ export default class CredentialLibrarySerializer extends ApplicationSerializer {
|
||||
if (!serialized.attributes?.http_method?.match(/post/i)) {
|
||||
serialized.attributes.http_request_body = null;
|
||||
}
|
||||
const { credential_type, credential_mapping_overrides } = serialized;
|
||||
|
||||
// API expects to send null to fields if it is undefined or deleted
|
||||
if (credential_mapping_overrides && !isNew) {
|
||||
serialized.credential_mapping_overrides = options.mapping_overrides[
|
||||
credential_type
|
||||
].reduce((obj, key) => {
|
||||
if (credential_mapping_overrides[key]) {
|
||||
obj[key] = credential_mapping_overrides[key];
|
||||
} else {
|
||||
obj[key] = null;
|
||||
}
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
this.handleCredentialMappingOverrides(serialized, isNew);
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
@@ -74,4 +63,36 @@ export default class CredentialLibrarySerializer extends ApplicationSerializer {
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
|
||||
serializeVaultLdap(snapshot) {
|
||||
const { isNew } = snapshot;
|
||||
const serialized = super.serialize(...arguments);
|
||||
if (serialized.attributes) {
|
||||
this.handleCredentialMappingOverrides(serialized, isNew);
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle credential mapping overrides for serialization.
|
||||
* @param {Object} serialized - The serialized object.
|
||||
* @param {boolean} isNew - Indicates if the record is new.
|
||||
*/
|
||||
handleCredentialMappingOverrides(serialized, isNew) {
|
||||
const { credential_type, credential_mapping_overrides } = serialized;
|
||||
|
||||
// API expects to send null to fields if it is undefined or deleted
|
||||
if (credential_mapping_overrides && !isNew) {
|
||||
serialized.credential_mapping_overrides = options.mapping_overrides[
|
||||
credential_type
|
||||
].reduce((obj, key) => {
|
||||
if (credential_mapping_overrides[key]) {
|
||||
obj[key] = credential_mapping_overrides[key];
|
||||
} else {
|
||||
obj[key] = null;
|
||||
}
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import generateId from '../helpers/id';
|
||||
import {
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
TYPES_CREDENTIAL_LIBRARY,
|
||||
options,
|
||||
} from 'api/models/credential-library';
|
||||
@@ -22,6 +23,9 @@ export default factory.extend({
|
||||
if (this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC) {
|
||||
return options.credential_types[i % options.credential_types.length];
|
||||
}
|
||||
if (this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP) {
|
||||
return options.credential_types[2]; // Only supports username, password & domain credential type
|
||||
}
|
||||
},
|
||||
authorized_actions: () =>
|
||||
permissions.authorizedActionsFor('credential-library') || [
|
||||
@@ -45,6 +49,10 @@ export default factory.extend({
|
||||
key_bits: faker.number.int(999),
|
||||
path: faker.system.directoryPath(),
|
||||
};
|
||||
case TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP:
|
||||
return {
|
||||
path: faker.system.directoryPath(),
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -58,7 +58,7 @@ export default factory.extend({
|
||||
const { scope, type } = credentialStore;
|
||||
switch (type) {
|
||||
case 'vault':
|
||||
server.createList('credential-library', 2, {
|
||||
server.createList('credential-library', 3, {
|
||||
scope,
|
||||
credentialStore,
|
||||
});
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC } from 'api/models/credential-library';
|
||||
import {
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
} from 'api/models/credential-library';
|
||||
|
||||
module('Unit | Model | credential library', function (hooks) {
|
||||
setupTest(hooks);
|
||||
@@ -22,10 +26,18 @@ module('Unit | Model | credential library', function (hooks) {
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
});
|
||||
const modelB = store.createRecord('credential-library', {
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
});
|
||||
const modelC = store.createRecord('credential-library', {
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
});
|
||||
const modelD = store.createRecord('credential-library', {
|
||||
type: 'unknown',
|
||||
});
|
||||
|
||||
assert.false(modelA.isUnknown);
|
||||
assert.true(modelB.isUnknown);
|
||||
assert.false(modelB.isUnknown);
|
||||
assert.false(modelC.isUnknown);
|
||||
assert.true(modelD.isUnknown);
|
||||
});
|
||||
});
|
||||
@@ -8,6 +8,7 @@ import { setupTest } from 'ember-qunit';
|
||||
import {
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
} from 'api/models/credential-library';
|
||||
|
||||
module('Unit | Serializer | credential library', function (hooks) {
|
||||
@@ -109,6 +110,7 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
let serializedVaultGenericRecord = vaultGenericRecord.serialize();
|
||||
let serializedVaultSSHCertificateRecord =
|
||||
vaultSSHCertificateRecord.serialize();
|
||||
|
||||
assert.deepEqual(serializedVaultGenericRecord, {
|
||||
attributes: {
|
||||
path: null,
|
||||
@@ -279,4 +281,82 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
version: 1,
|
||||
});
|
||||
});
|
||||
|
||||
test('it serializes vault-ldap correctly on create', function (assert) {
|
||||
const store = this.owner.lookup('service:store');
|
||||
const serializer = store.serializerFor('credential-library');
|
||||
const record = store.createRecord('credential-library', {
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
name: 'Name',
|
||||
description: 'Description',
|
||||
path: '/vault/path',
|
||||
version: 1,
|
||||
credential_type: 'username_password_domain',
|
||||
credential_mapping_overrides: [
|
||||
{ key: 'username_attribute', value: 'user' },
|
||||
{ key: 'domain_attribute', value: 'domain' },
|
||||
],
|
||||
});
|
||||
const snapshot = record._createSnapshot();
|
||||
const serializedRecord = serializer.serialize(snapshot);
|
||||
|
||||
assert.deepEqual(serializedRecord, {
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
credential_store_id: null,
|
||||
name: 'Name',
|
||||
description: 'Description',
|
||||
version: 1,
|
||||
credential_type: 'username_password_domain',
|
||||
credential_mapping_overrides: {
|
||||
username_attribute: 'user',
|
||||
domain_attribute: 'domain',
|
||||
},
|
||||
attributes: {
|
||||
path: '/vault/path',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('it serializes vault-ldap correctly on update', function (assert) {
|
||||
const store = this.owner.lookup('service:store');
|
||||
const serializer = store.serializerFor('credential-library');
|
||||
store.push({
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'credential-library',
|
||||
attributes: {
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
name: 'Name',
|
||||
description: 'Description',
|
||||
path: '/vault/path',
|
||||
version: 1,
|
||||
credential_type: 'username_password_domain',
|
||||
credential_mapping_overrides: [
|
||||
{ key: 'username_attribute', value: 'user' },
|
||||
{ key: 'domain_attribute', value: 'domain' },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
const record = store.peekRecord('credential-library', '1');
|
||||
const snapshot = record._createSnapshot();
|
||||
const serializedRecord = serializer.serialize(snapshot);
|
||||
|
||||
assert.deepEqual(serializedRecord, {
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
|
||||
credential_store_id: null,
|
||||
name: 'Name',
|
||||
description: 'Description',
|
||||
version: 1,
|
||||
credential_type: 'username_password_domain',
|
||||
credential_mapping_overrides: {
|
||||
username_attribute: 'user',
|
||||
domain_attribute: 'domain',
|
||||
password_attribute: null,
|
||||
},
|
||||
attributes: {
|
||||
path: '/vault/path',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -966,6 +966,7 @@ credential-library:
|
||||
types:
|
||||
vault-generic: Generic Secrets
|
||||
vault-ssh-certificate: SSH Certificates
|
||||
vault-ldap: LDAP
|
||||
help:
|
||||
vault-generic: Authorize sessions using credentials brokered by Vault
|
||||
vault-ssh-certificate: Authorize sessions using the SSH Secrets Engine in Vault
|
||||
|
||||
Reference in new issue
Block a user