- [MAJOR] Added the ability for profiles to securly store credentials using a credential manager.
- [MAJOR] AbstractProfileManager now calls the Credential Manager to save, load and delete credentials of a profile.
- [MINOR] ICommandOptionDefinition now contains types for
username
andpassword
Part of this effort involved creating a way to securly store and load credentials in Imperative. This involved creating a credential manager.
- [MAJOR] Created a new
security
package - [MAJOR] Created a DefaultCredentialManager which utilizes keytar to perform the storing and loading of credentials.
- [MAJOR] keytar is an optional dependency that needs special setup on Linux. If keytar was not installed, a command will only fail if the DefaultCredentialManager tries to save/load/delete credentials. Otherwise everything will just work fine.
- [MAJOR] Created an OverridesLoader underneath the imperative package and defined a property
- [MAJOR] Provided the ability for a CLI to override the default credential manager. See section below.
- [MINOR] Exposed a CredentialManagerFactory to abstract how Imperative accesses the underlying manager securly.
It is possible for a CLI to override the DefaultCredentialManager by specifying the overrides.CredentialManager property on the config. The class specified must properly extend AbstractCredentialManager.
// Using a string path
{
//...
overrides: {
CredentialManager: "path/to/CredentialManager.ts" // requires module.exports to be the manager.
}
//...
}
// Or using the actual class
{
//...
overrides: {
CredentialManager: require("path/to/CredentialManager.ts")
}
//...
}
// In path/to/CredentialManager.ts
export = class CredentialManager extends AbstractCredentialManager {
/**
* Create a constructor that satisfies ICredentialManagerConstructor
*
* @param service Passed by Imperative
*/
constructor(service: string) {
super(service);
}
/**
* In the example, we always will return a hardcoded string.
*
* @param {string} account Passed to this function by Imperative
*/
protected async loadCredentials(account: string): Promise<SecureCredential> {
return Buffer.from("username-goes-here:password-goes-here").toString("base64");
}
/**
* In the example, we do nothing.
*
* @param {string} account Passed to this function by Imperative
* @param {SecureCredential} credentials Passed to this function by Imperative
*/
protected async saveCredentials(account: string, credentials: SecureCredential): Promise<void> {
return;
}
/**
* In the example, we do nothing.
*
* @param account Passed to this function by Imperative
*/
protected async deleteCredentials(account: string): Promise<void> {
return;
}
};