Skip to content
This repository has been archived by the owner on Mar 27, 2019. It is now read-only.

Commit

Permalink
Merge pull request #31 from djenriquez/support-multiple-backends
Browse files Browse the repository at this point in the history
Support multiple backends
  • Loading branch information
DJ Enriquez authored Dec 27, 2016
2 parents 61be12f + ee31982 commit 9c3fd9b
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 35 deletions.
113 changes: 86 additions & 27 deletions app/components/Secrets/Secrets.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,21 @@ class Secrets extends React.Component {
disableTextField: false,
focusKey: '',
focusSecret: '',
listBackends: false,
secretBackends: [],
secrets: [],
namespace: '/',
namespace: '/secret/',
useRootKey: window.localStorage.getItem("useRootKey") === 'true' || false,
rootKey: window.localStorage.getItem("secretsRootKey") || '',
forbidden: false,
disableAddButton: false,
buttonColor: 'lightgrey'
};

_.bindAll(
this,
'listSecretBackends',
'getSecrets',
'renderSecrets',
'renderList',
'renderNamespace',
'clickSecret',
'secretChanged',
Expand All @@ -57,7 +60,8 @@ class Secrets extends React.Component {
}

componentWillMount() {
this.getSecrets("/");
this.listSecretBackends();
this.getSecrets(this.state.namespace);
}

copyText(value) {
Expand Down Expand Up @@ -228,9 +232,9 @@ class Secrets extends React.Component {
var rootKeyInfo;

if (this.state.useRootKey) {
rootKeyInfo = "Current Root Key: " + this.state.rootKey;
rootKeyInfo = "Current Root Key: " + this.state.rootKey;
} else {
rootKeyInfo = "No Root Key set. Value must be JSON.";
rootKeyInfo = "No Root Key set. Value must be JSON.";
}

return (
Expand All @@ -255,6 +259,31 @@ class Secrets extends React.Component {
);
}

listSecretBackends() {
axios.get(`/listsecretbackends?vaultaddr=${encodeURI(window.localStorage.getItem("vaultUrl"))}&token=${encodeURI(window.localStorage.getItem("vaultAccessToken"))}`)
.then((resp) => {
var secretBackends = [];
_.forEach(Object.keys(resp.data.data), (key) => {
if (resp.data.data[key].type == "generic") {
secretBackends.push({ key: key });
}
});
this.setState({
secretBackends: secretBackends,
disableAddButton: false,
buttonColor: green500
});
})
.catch((err) => {
console.error(err.response.data);
this.setState({
errorMessage: err.response.data,
disableAddButton: true,
buttonColor: 'lightgrey'
});
});
}

getSecrets(namespace) {
axios.get(`/listsecrets?vaultaddr=${encodeURI(window.localStorage.getItem("vaultUrl"))}&token=${encodeURI(window.localStorage.getItem("vaultAccessToken"))}&namespace=${encodeURI(namespace)}`)
.then((resp) => {
Expand All @@ -267,15 +296,15 @@ class Secrets extends React.Component {
this.setState({
namespace: namespace,
secrets: secrets,
forbidden: false,
disableAddButton: false,
buttonColor: green500
});
})
.catch((err) => {
console.error(err.response.data);
this.setState({
errorMessage: err.response.data,
forbidden: true,
disableAddButton: true,
buttonColor: 'lightgrey'
});
});
Expand All @@ -300,7 +329,8 @@ class Secrets extends React.Component {
focusSecret: '',
disableSubmit: true,
openEditModal: true,
disableTextField: true
disableTextField: true,
listBackends: false
});
} else {
val = typeof val == 'object' ? JSON.stringify(val) : val;
Expand All @@ -310,14 +340,14 @@ class Secrets extends React.Component {
disableTextField: false,
openEditModal: true,
focusKey: key,
focusSecret: val
focusSecret: val,
listBackends: false
});
}
})
.catch((err) => {
console.error(err.stack);
});

}
}

Expand All @@ -341,19 +371,41 @@ class Secrets extends React.Component {
}
}

renderSecrets() {
return _.map(this.state.secrets, (secret) => {
return (
<ListItem
style={{ marginLeft: -17 }}
key={secret.key}
onTouchTap={() => { this.clickSecret(secret.key) } }
primaryText={<div className={styles.key}>{secret.key}</div>}
//secondaryText={<div className={styles.key}>{secret.value}</div>}
rightIconButton={this.showDelete(secret.key)}>
</ListItem>
);
});
renderList() {
if (this.state.listBackends) {
return _.map(this.state.secretBackends, (secretBackend) => {
return (
<ListItem
style={{ marginLeft: -17 }}
key={secretBackend.key}
onTouchTap={() => {
this.setState(
{
namespace: '/' + secretBackend.key,
listBackends: false,
secrets: this.getSecrets('/' + secretBackend.key)
})
} }
primaryText={<div className={styles.key}>{secretBackend.key}</div>}
//secondaryText={<div className={styles.key}>{secret.value}</div>}
>
</ListItem>
);
});
} else {
return _.map(this.state.secrets, (secret) => {
return (
<ListItem
style={{ marginLeft: -17 }}
key={secret.key}
onTouchTap={() => { this.clickSecret(secret.key) } }
primaryText={<div className={styles.key}>{secret.key}</div>}
//secondaryText={<div className={styles.key}>{secret.value}</div>}
rightIconButton={this.showDelete(secret.key)}>
</ListItem>
);
});
}
}

renderNamespace() {
Expand All @@ -364,7 +416,14 @@ class Secrets extends React.Component {
return (
<div style={{ display: 'inline-block' }} key={index}>
<span className={styles.link}
onTouchTap={() => this.clickSecret("/", true)}>ROOT</span>
onTouchTap={() => this.setState(
{
listBackends: true,
namespace: '/',
disableAddButton: true,
buttonColor: 'lightgrey'
})}
>ROOT</span>
{index !== namespaceParts.length - 1 && <span>/</span>}
</div>
);
Expand Down Expand Up @@ -392,13 +451,13 @@ class Secrets extends React.Component {
<FlatButton
label="Add Key"
backgroundColor={this.state.buttonColor}
disabled={this.state.forbidden}
disabled={this.state.disableAddButton}
hoverColor={green400}
labelStyle={{ color: white }}
onTouchTap={() => this.setState({ openNewKeyModal: true, focusKey: '', focusSecret: '', errorMessage: '' })} />
<div className={styles.namespace}>{this.renderNamespace()}</div>
<List>
{this.renderSecrets()}
{this.renderList()}
</List>
</div>
);
Expand Down
4 changes: 4 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ app.post('/login', function (req, res) {
routeHandler.login(req, res);
});

app.get('/listsecretbackends', function (req, res) {
routeHandler.listSecretBackends(req, res);
});

app.get('/listsecrets', function (req, res) {
routeHandler.listSecrets(req, res);
});
Expand Down
1 change: 1 addition & 0 deletions src/routeHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var respwrapping = require('./respwrapping');
module.exports = (function () {
return {
login: login.login,
listSecretBackends: secrets.listSecretBackends,
listSecrets: secrets.listSecrets,
getSecret: secrets.getSecret,
writeSecret: secrets.writeSecret,
Expand Down
49 changes: 41 additions & 8 deletions src/secrets.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,42 @@
var axios = require('axios');
var _ = require('lodash');

/* Returned body
{
"aws": {
"type": "aws",
"description": "AWS keys",
"config": {
"default_lease_ttl": 0,
"max_lease_ttl": 0
}
},
"sys": {
"type": "system",
"description": "system endpoint",
"config": {
"default_lease_ttl": 0,
"max_lease_ttl": 0
}
}
}
*/
exports.listSecretBackends = function (req, res) {
let endpoint = `/v1/sys/mounts`;
let vaultAddr = decodeURI(req.query['vaultaddr']);
let config = { headers: { 'X-Vault-Token': decodeURI(req.query['token']) } }

axios.get(`${vaultAddr}${endpoint}`, config)
.then((resp) => {
res.json(resp.data);
})
.catch((err) => {
console.error(err.stack);
res.status(err.response.status).send(err.response);
});
}

/* Returned body
{
"auth": null,
Expand All @@ -15,9 +51,8 @@ var _ = require('lodash');
}
*/
exports.listSecrets = function (req, res) {

let namespace = decodeURI(req.query['namespace']);
let endpoint = `/v1/secret${namespace}?list=true`;
let endpoint = `/v1${namespace}?list=true`;
let vaultAddr = decodeURI(req.query['vaultaddr']);
let config = { headers: { 'X-Vault-Token': decodeURI(req.query['token']) } }

Expand All @@ -37,7 +72,7 @@ exports.listSecrets = function (req, res) {
Query params 'secret' and 'vaultaddr' must go through encodeURI()
*/
exports.getSecret = function (req, res) {
let endpoint = `/v1/secret/${decodeURI(req.query['secret'])}`;
let endpoint = `/v1${decodeURI(req.query['secret'])}`;
let vaultAddr = decodeURI(req.query['vaultaddr']);
let config = { headers: { 'X-Vault-Token': req.query['token'] } }

Expand All @@ -52,8 +87,7 @@ exports.getSecret = function (req, res) {
}

exports.writeSecret = function (req, res) {

let endpoint = `/v1/secret${decodeURI(req.query['secret'])}`;
let endpoint = `/v1${decodeURI(req.query['secret'])}`;
let config = { headers: { 'X-Vault-Token': req.query['token'] } }

let body = _.get(req, "body.Value")
Expand All @@ -74,10 +108,10 @@ exports.writeSecret = function (req, res) {
}

exports.deleteSecret = function (req, res) {
let endpoint = `/v1/secret${decodeURI(req.query['secret'])}`;
let endpoint = `/v1${decodeURI(req.query['secret'])}`;
let config = { headers: { 'X-Vault-Token': req.query['token'] } }
let vaultAddr = decodeURI(req.query['vaultaddr']);

axios.delete(`${vaultAddr}${endpoint}`, config)
.then((resp) => {
res.sendStatus(resp.status);
Expand All @@ -87,4 +121,3 @@ exports.deleteSecret = function (req, res) {
res.status(err.response.status).send(err.response);
})
}

0 comments on commit 9c3fd9b

Please sign in to comment.