Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
robert-cronin committed Oct 14, 2020
1 parent 6f6a8c1 commit f5b0d80
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 83 deletions.
10 changes: 9 additions & 1 deletion openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ paths:
text/plain:
schema:
type: string
application/octet-stream:
schema:
type: string
format: binary
"401":
description: Not authenticated
"403":
Expand All @@ -222,11 +226,15 @@ paths:
- bearerAuth: [admin, write_secrets]
- OAuth2-Client: [admin, write_secrets]
requestBody:
description: Object describing the secret
description: Secret content
content:
text/plain:
schema:
type: string
application/octet-stream:
schema:
type: string
format: binary
responses:
"200":
description: Secret was created successfully
Expand Down
22 changes: 6 additions & 16 deletions src/Polykey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,15 @@ class Polykey {
}).bind(this),
((vaultName: string, secretName: string) => {
const vault = this.vaultManager.getVault(vaultName)
return vault.getSecret(secretName).toString()
return vault.getSecret.bind(vault)(secretName)
}).bind(this),
(async (vaultName: string, secretName: string, secretContent: string) => {
try {
const vault = this.vaultManager.getVault(vaultName)
await vault.addSecret(secretName, Buffer.from(secretContent))
return true
} catch (error) {
return false
}
(async (vaultName: string, secretName: string, secretContent: Buffer) => {
const vault = this.vaultManager.getVault(vaultName)
await vault.addSecret(secretName, secretContent)
}).bind(this),
(async (vaultName: string, secretName: string) => {
try {
const vault = this.vaultManager.getVault(vaultName)
await vault.removeSecret(secretName)
return true
} catch (error) {
return false
}
const vault = this.vaultManager.getVault(vaultName)
await vault.removeSecret(secretName)
}).bind(this),
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/agent/PolykeyAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class PolykeyAgent implements IAgentServer {
private noThrowRefreshTimeout() {
try {
this.pk.keyManager.refreshTimeout();
} catch (error) {}
} catch (error) { }
}

async addPeer(
Expand Down Expand Up @@ -863,7 +863,7 @@ class PolykeyAgent implements IAgentServer {
if (this.pk.keyManager.identityLoaded) {
this.pk.keyManager.refreshTimeout(timeout);
} else {
await this.pk.keyManager.unlockIdentity(passphrase,timeout);
await this.pk.keyManager.unlockIdentity(passphrase, timeout);
}

// re-load all meta data
Expand Down
167 changes: 103 additions & 64 deletions src/api/HttpApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import path from 'path';
import http from 'http';
import https from 'https';
import jsyaml from 'js-yaml';
import express from 'express';
import express, { RequestHandler } from 'express';
import passport from 'passport'
import { getPort } from '../utils';
import session from 'express-session'
Expand All @@ -19,6 +19,7 @@ import { User, Client } from './AuthorizationServer/OAuth2Store';
import { Strategy as BearerStrategy } from 'passport-http-bearer';
import { TLSCredentials } from '../keys/pki/PublicKeyInfrastructure';
import { Strategy as ClientPasswordStrategy } from 'passport-oauth2-client-password';
import { DEFAULT_ENCODING } from 'crypto';

class HttpApi {
private openApiPath: string
Expand All @@ -31,9 +32,9 @@ class HttpApi {
private newVault: (vaultName: string) => Promise<void>;
private deleteVault: (vaultName: string) => Promise<void>;
private listSecrets: (vaultName: string) => string[];
private getSecret: (vaultName: string, secretName: string) => string;
private newSecret: (vaultName: string, secretName: string, secretContent: string) => Promise<boolean>;
private deleteSecret: (vaultName: string, secretName: string) => Promise<boolean>;
private getSecret: (vaultName: string, secretName: string) => Buffer;
private newSecret: (vaultName: string, secretName: string, secretContent: Buffer) => Promise<void>;
private deleteSecret: (vaultName: string, secretName: string) => Promise<void>;

private tlsCredentials: TLSCredentials
private oauth: OAuth2
Expand All @@ -50,9 +51,9 @@ class HttpApi {
newVault: (vaultName: string) => Promise<void>,
deleteVault: (vaultName: string) => Promise<void>,
listSecrets: (vaultName: string) => string[],
getSecret: (vaultName: string, secretName: string) => string,
newSecret: (vaultName: string, secretName: string, secretContent: string) => Promise<boolean>,
deleteSecret: (vaultName: string, secretName: string) => Promise<boolean>,
getSecret: (vaultName: string, secretName: string) => Buffer,
newSecret: (vaultName: string, secretName: string, secretContent: string | Buffer) => Promise<void>,
deleteSecret: (vaultName: string, secretName: string) => Promise<void>,
) {
// this code is needed as we can't require yaml files
const fromSrcFolderPath = path.join(__dirname, '../../openapi.yaml')
Expand Down Expand Up @@ -109,7 +110,7 @@ class HttpApi {
this.expressServer.use(passport.session());

// redirect from base url to docs
this.expressServer.get('/',(req, res, next) => {
this.expressServer.get('/', (req, res, next) => {
res.redirect('/docs')
})

Expand Down Expand Up @@ -261,120 +262,158 @@ class HttpApi {
}

// === openapi endpoints === //
private handleCertificateSigningRequest = async (req, res, next) => {
private handleRootCertificateRequest: RequestHandler = async (req, res, next) => {
try {
const body = req.body;
const response = this.handleCSR(body);
this.writeJson(res, response);
const response = this.getRootCertificate();
this.writeString(res, response);
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

private handleRootCertificateRequest = async (req, res, next) => {
private handleCertificateChainRequest: RequestHandler = async (req, res, next) => {
try {
const response = this.getRootCertificate();
this.writeJson(res, response);
const response = this.getCertificateChain();
this.writeStringList(res, response);
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

private handleCertificateChainRequest = async (req, res, next) => {
private handleCertificateSigningRequest: RequestHandler = async (req, res, next) => {
try {
const response = this.getCertificateChain();
this.writeJson(res, response);
const body = req.body;
const response = this.handleCSR(body);
this.writeString(res, response);
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

private handleVaultsListRequest = async (req, res, next) => {
private handleVaultsListRequest: RequestHandler = async (req, res, next) => {
try {
const response = this.getVaultNames()
this.writeJson(res, response);
this.writeStringList(res, response);
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

private handleNewVaultRequest = async (req, res, next) => {
private handleNewVaultRequest: RequestHandler = async (req, res, next) => {
try {
const vaultName = req.openapi.pathParams.vaultName;
const vaultName = (<any>req).openapi.pathParams.vaultName;
await this.newVault(vaultName)
this.writeJson(res);
this.writeSuccess(res);
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

private handleDeleteVaultRequest = async (req, res, next) => {
private handleDeleteVaultRequest: RequestHandler = async (req, res, next) => {
try {
const vaultName = req.openapi.pathParams.vaultName;
const vaultName = (<any>req).openapi.pathParams.vaultName;
await this.deleteVault(vaultName)
this.writeJson(res);
this.writeSuccess(res);
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

private handleSecretsListRequest = async (req, res, next) => {
private handleSecretsListRequest: RequestHandler = async (req, res, next) => {
try {
const vaultName = req.openapi.pathParams.vaultName;
const vaultName = (<any>req).openapi.pathParams.vaultName;
const response = this.listSecrets(vaultName);
this.writeJson(res, response);
this.writeStringList(res, response);
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

private handleGetSecretRequest = async (req, res, next) => {
private handleGetSecretRequest: RequestHandler = async (req, res, next) => {
try {
const vaultName = req.openapi.pathParams.vaultName;
const secretName = req.openapi.pathParams.secretName;

const vaultName = (<any>req).openapi.pathParams.vaultName;
const secretName = (<any>req).openapi.pathParams.secretName;
const response = this.getSecret(vaultName, secretName)
this.writeJson(res, response);

const accepts = req.accepts()[0]
if (accepts == 'text/plain') {
this.writeString(res, response.toString())
} else if (accepts == 'application/octet-stream') {
this.writeBinary(res, secretName, response);
} else {
throw Error('MIME type not supported')
}
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

private handleNewSecretRequest = async (req, res, next) => {
private handleNewSecretRequest: RequestHandler = async (req, res, next) => {
try {
const vaultName = req.openapi.pathParams.vaultName;
const secretName = req.openapi.pathParams.secretName;
const secretContent = req.body
const vaultName = (<any>req).openapi.pathParams.vaultName;
const secretName = (<any>req).openapi.pathParams.secretName;

let secretContent: Buffer
const contentType = req.headers['content-type']
if (contentType == 'text/plain') {
secretContent = Buffer.from(req.body)
} else if (contentType == 'application/octet-stream') {
secretContent = await new Promise<Buffer>((resolve, reject) => {
const bufferList: Buffer[] = []
req.on('data', (data) => bufferList.push(data))
req.on('error', (err) => reject(err))
req.on('end', () => resolve(Buffer.concat(bufferList)))
})
} else {
throw Error('MIME type not supported')
}

await this.newSecret(vaultName, secretName, secretContent);
this.writeJson(res);
this.writeSuccess(res);
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

private handleDeleteSecretRequest = async (req, res, next) => {
private handleDeleteSecretRequest: RequestHandler = async (req, res, next) => {
try {
const vaultName = req.openapi.pathParams.vaultName;
const secretName = req.openapi.pathParams.secretName;
const vaultName = (<any>req).openapi.pathParams.vaultName;
const secretName = (<any>req).openapi.pathParams.secretName;
await this.deleteSecret(vaultName, secretName);
this.writeJson(res);
this.writeSuccess(res);
} catch (error) {
this.writeJson(res, error);
this.writeError(res, error);
}
};

// === Helper methods === //
private writeJson(response: http.ServerResponse, payload?: string | Object | Error | Array<any>, code: number = 200) {
let responseString: string | undefined
if (!payload) {
responseString = undefined
} else if (payload instanceof Error) {
code = 500
responseString = JSON.stringify({ error: payload.message }, null, 2);
} else {
responseString = JSON.stringify(payload, null, 2);
}
response.writeHead(code, { 'Content-Type': 'application/json' });
response.end(responseString);
private writeSuccess(res: http.ServerResponse) {
res.writeHead(200);
res.end();
}
private writeError(res: http.ServerResponse, error: Error) {
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: error.message }, null, 2));
}
private writeString(res: http.ServerResponse, text: string) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(text);
}
private writeStringList(res: http.ServerResponse, list: string[]) {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(list, null, 2));
}
private writeJson(res: http.ServerResponse, payload: Object) {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(payload, null, 2));
}
private writeBinary(res: http.ServerResponse, filename: string, payload: Buffer) {
res.writeHead(200, {
'Content-Type': 'application/octet-stream',
'Content-Disposition': `file; filename="${filename}"`
});
res.end(payload, 'binary');
}

private checkScope(scope: string[]) {
Expand Down

0 comments on commit f5b0d80

Please sign in to comment.