added the vault

This commit is contained in:
Eugene Pankov
2021-06-05 17:38:11 +02:00
parent 17471096f2
commit 7f18396926
17 changed files with 867 additions and 17 deletions

View File

@@ -0,0 +1,20 @@
h3.modal-header.m-0.pb-0 Set master passphrase
.modal-body
.mb-2 You can change it later, but it's unrecoverable if forgotten.
.input-group
input.form-control.form-control-lg(
[type]='showPassphrase ? "text" : "password"',
autofocus,
[(ngModel)]='passphrase',
#input,
placeholder='Master passphrase',
(keyup.enter)='ok()',
(keyup.esc)='cancel()',
)
.input-group-append
button.btn.btn-secondary((click)='showPassphrase = !showPassphrase')
i.fas.fa-eye
.modal-footer
button.btn.btn-outline-primary((click)='ok()') Set passphrase
button.btn.btn-outline-danger((click)='cancel()') Cancel

View File

@@ -0,0 +1,29 @@
import { Component, ViewChild, ElementRef } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
/** @hidden */
@Component({
template: require('./setVaultPassphraseModal.component.pug'),
})
export class SetVaultPassphraseModalComponent {
passphrase: string
@ViewChild('input') input: ElementRef
constructor (
private modalInstance: NgbActiveModal,
) { }
ngOnInit (): void {
setTimeout(() => {
this.input.nativeElement.focus()
})
}
ok (): void {
this.modalInstance.close(this.passphrase)
}
cancel (): void {
this.modalInstance.close(null)
}
}

View File

@@ -0,0 +1,35 @@
.text-center(*ngIf='!vault.enabled')
i.fas.fa-key.fa-3x.m-3
h3.m-3 Vault is not configured
.m-3 Vault is an always-encrypted container for secrets such as SSH passwords and private key passphrases.
button.btn.btn-primary.m-2((click)='enableVault()') Set master passphrase
div(*ngIf='vault.enabled')
.d-flex.align-items-center.mb-3
h3.m-0 Vault
.d-flex.ml-auto(ngbDropdown, *ngIf='vault.enabled')
button.btn.btn-secondary(ngbDropdownToggle) Options
div(ngbDropdownMenu)
a(ngbDropdownItem, (click)='changePassphrase()')
i.fas.fa-fw.fa-key
span Change the master passphrase
a(ngbDropdownItem, (click)='disableVault()')
i.fas.fa-fw.fa-radiation-alt
span Erase the vault
div(*ngIf='vaultContents')
.text-center(*ngIf='!vaultContents.secrets.length')
i.fas.fa-empty-set.fa-3x
h3.m-3 Vault is empty
.list-group
.list-group-item.d-flex.align-items-center.p-1.pl-3(*ngFor='let secret of vaultContents.secrets')
i.fas.fa-key
.mr-auto {{getSecretLabel(secret)}}
button.btn.btn-link((click)='removeSecret(secret)')
i.fas.fa-trash
.text-center(*ngIf='!vaultContents')
i.fas.fa-key.fa-3x
h3.m-3 Vault is locked
button.btn.btn-primary.m-2((click)='loadVault()') Show vault contents

View File

@@ -0,0 +1,80 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { BaseComponent, VaultService, VaultSecret, Vault, PlatformService } from 'terminus-core'
import { SetVaultPassphraseModalComponent } from './setVaultPassphraseModal.component'
/** @hidden */
@Component({
selector: 'vault-settings-tab',
template: require('./vaultSettingsTab.component.pug'),
})
export class VaultSettingsTabComponent extends BaseComponent {
vaultContents: Vault|null = null
constructor (
public vault: VaultService,
private platform: PlatformService,
private ngbModal: NgbModal,
) {
super()
if (vault.isOpen()) {
this.loadVault()
}
}
async loadVault (): Promise<void> {
this.vaultContents = await this.vault.load()
}
async enableVault () {
const modal = this.ngbModal.open(SetVaultPassphraseModalComponent)
const newPassphrase = await modal.result
await this.vault.setEnabled(true, newPassphrase)
this.vaultContents = await this.vault.load(newPassphrase)
}
async disableVault () {
if ((await this.platform.showMessageBox(
{
type: 'warning',
message: 'Delete vault contents?',
buttons: ['Keep', 'Delete'],
defaultId: 1,
}
)).response === 1) {
await this.vault.setEnabled(false)
}
}
async changePassphrase () {
if (!this.vaultContents) {
this.vaultContents = await this.vault.load()
}
if (!this.vaultContents) {
return
}
const modal = this.ngbModal.open(SetVaultPassphraseModalComponent)
const newPassphrase = await modal.result
this.vault.save(this.vaultContents, newPassphrase)
}
getSecretLabel (secret: VaultSecret) {
if (secret.type === 'ssh:password') {
return `SSH password for ${secret.key.user}@${secret.key.host}:${secret.key.port}`
}
if (secret.type === 'ssh:key-passphrase') {
return `Passphrase for a private key with hash ${secret.key.hash.substring(0, 8)}...`
}
return `Unknown secret of type ${secret.type} for ${JSON.stringify(secret.key)}`
}
removeSecret (secret: VaultSecret) {
if (!this.vaultContents) {
return
}
this.vaultContents.secrets = this.vaultContents.secrets.filter(x => x !== secret)
this.vault.removeSecret(secret.type, secret.key)
}
}

View File

@@ -11,12 +11,14 @@ import { MultiHotkeyInputComponent } from './components/multiHotkeyInput.compone
import { SettingsTabComponent } from './components/settingsTab.component'
import { SettingsTabBodyComponent } from './components/settingsTabBody.component'
import { WindowSettingsTabComponent } from './components/windowSettingsTab.component'
import { VaultSettingsTabComponent } from './components/vaultSettingsTab.component'
import { SetVaultPassphraseModalComponent } from './components/setVaultPassphraseModal.component'
import { SettingsTabProvider } from './api'
import { ButtonProvider } from './buttonProvider'
import { SettingsHotkeyProvider } from './hotkeys'
import { SettingsConfigProvider } from './config'
import { HotkeySettingsTabProvider, WindowSettingsTabProvider } from './settings'
import { HotkeySettingsTabProvider, WindowSettingsTabProvider, VaultSettingsTabProvider } from './settings'
/** @hidden */
@NgModule({
@@ -32,11 +34,14 @@ import { HotkeySettingsTabProvider, WindowSettingsTabProvider } from './settings
{ provide: HotkeyProvider, useClass: SettingsHotkeyProvider, multi: true },
{ provide: SettingsTabProvider, useClass: HotkeySettingsTabProvider, multi: true },
{ provide: SettingsTabProvider, useClass: WindowSettingsTabProvider, multi: true },
{ provide: SettingsTabProvider, useClass: VaultSettingsTabProvider, multi: true },
],
entryComponents: [
HotkeyInputModalComponent,
HotkeySettingsTabComponent,
SettingsTabComponent,
SetVaultPassphraseModalComponent,
VaultSettingsTabComponent,
WindowSettingsTabComponent,
],
declarations: [
@@ -45,6 +50,8 @@ import { HotkeySettingsTabProvider, WindowSettingsTabProvider } from './settings
MultiHotkeyInputComponent,
SettingsTabComponent,
SettingsTabBodyComponent,
SetVaultPassphraseModalComponent,
VaultSettingsTabComponent,
WindowSettingsTabComponent,
],
})

View File

@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'
import { SettingsTabProvider } from './api'
import { HotkeySettingsTabComponent } from './components/hotkeySettingsTab.component'
import { WindowSettingsTabComponent } from './components/windowSettingsTab.component'
import { VaultSettingsTabComponent } from './components/vaultSettingsTab.component'
/** @hidden */
@Injectable()
@@ -27,3 +28,16 @@ export class WindowSettingsTabProvider extends SettingsTabProvider {
return WindowSettingsTabComponent
}
}
/** @hidden */
@Injectable()
export class VaultSettingsTabProvider extends SettingsTabProvider {
id = 'vault'
icon = 'key'
title = 'Vault'
getComponentType (): any {
return VaultSettingsTabComponent
}
}