get credentials from AWS secrets manager

This commit is contained in:
Gabriel Rosa
2022-06-23 16:26:49 -03:00
parent a42ec164c3
commit d6552678a8
11 changed files with 112 additions and 53 deletions
+3 -3
View File
@@ -40,7 +40,7 @@ jobs:
docker-compose -f build.docker-compose.yml run -e NPM_TOKEN=${NPM_TOKEN} --rm --entrypoint="npm run test" maestro
- name: Remove Docker's Trash
continue-on-error: true
if: always()
run: |
docker system prune
docker rmi -f $(docker images -aq)
docker system prune --volumes -a -f
docker system df
+2
View File
@@ -33,6 +33,7 @@ import { CatalogController } from './modules/catalog/catalog.controller';
import { CatalogService } from './modules/catalog/catalog.service';
import { HubspotStrategy } from './modules/oauth/passport-strategies/hubspot';
import { OauthController } from './modules/oauth/oauth.controller';
import { getOauthSecrets } from './utils/OauthSecrets';
const authClient = new AuthClient();
const inputClient = new InputsClientConfiguration();
@@ -52,6 +53,7 @@ const transformationClient = new TransformationsClientConfiguration();
OauthController,
],
providers: [
{ provide: 'OAUTH_SECRETS', useValue: getOauthSecrets() },
InputsService,
TransformationsService,
OutputsService,
+11 -7
View File
@@ -3,6 +3,8 @@ import {
Inject,
HttpException,
HttpStatus,
NotFoundException,
InternalServerErrorException,
} from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import {
@@ -22,23 +24,20 @@ import {
objectSnakeToCamel,
} from 'src/utils/CaseConverter';
import { mustache } from 'src/utils/mustache';
import { OauthScrets } from 'src/utils/OauthSecrets';
import { OauthSecrets } from 'src/utils/OauthSecrets';
import { URLSearchParams } from 'url';
import { IIdRequest, UpdateInputRequest } from './interfaces';
export class InputsClientService implements OnModuleInit {
private inputService: InputService;
oauthSecrets: OauthScrets;
constructor(
@Inject('INPUTS_PACKAGE') private readonly grpcClient: ClientGrpc,
@Inject('OAUTH_SECRETS') private readonly oauthSecrets: OauthSecrets,
) {}
async onModuleInit() {
this.inputService =
this.grpcClient.getService<InputService>('InputService');
this.oauthSecrets = new OauthScrets();
await this.oauthSecrets.init();
console.log(this.oauthSecrets);
}
async newCreate(createInputDto: InputNewCreateRequest) {
@@ -54,7 +53,7 @@ export class InputsClientService implements OnModuleInit {
async createGeneric(createInputGeneric) {
console.log('InputClientService', 'Create');
const { info, ...data } = createInputGeneric;
data.credentials = await this.getInputTokens(data);
// data.credentials = await this.getInputTokens(data);
if (data.options) delete data.options;
if (data.credentials.oauth_code) delete data.credentials.oauth_code;
const grpcPayload = {
@@ -65,7 +64,12 @@ export class InputsClientService implements OnModuleInit {
const structReturn = await lastValueFrom(
this.inputService.Create(grpcPayload),
);
).catch((err) => {
if (err.details === 'Item Not found!') {
throw new NotFoundException('Input not found');
}
throw new InternalServerErrorException(err.details);
});
objectCamelToSnake(structReturn);
const inputCreated = DecodeGrpcStruct(structReturn.input);
return { input: inputCreated };
+2 -1
View File
@@ -26,7 +26,8 @@ async function bootstrap() {
const document = SwaggerModule.createDocument(app, config);
writeFileSync('./swagger.json', JSON.stringify(document));
SwaggerModule.setup('api', app, document);
if (process.env.ENV != 'stg' && process.env.ENV != 'prd')
SwaggerModule.setup('api', app, document);
await app.listen(3333);
}
+2
View File
@@ -170,6 +170,8 @@ export class TestConnectionRes {
database_tables: string[];
}
export class CreateInputReq {
@ApiPropertyOptional()
id: string;
@ApiProperty()
plugin: string;
@ApiProperty()
+18 -16
View File
@@ -46,8 +46,7 @@ export class InputsController {
async testConnection(@Body() data: TestConnectionReq) {
console.log(`/test-connection`, 'ON TEST CONNECTION ROUTE');
const inputService = new InputsService(this.inputsClientService);
const response = await inputService.testConnection(data);
const response = await this.inputService.testConnection(data);
return response;
}
@@ -60,8 +59,7 @@ export class InputsController {
'ON TEST CONNECTION GET COLUMNS ROUTE',
);
const inputService = new InputsService(this.inputsClientService);
const response = await inputService.getColumns(data);
const response = await this.inputService.getColumns(data);
return response;
}
@@ -71,8 +69,18 @@ export class InputsController {
async create(@Body() createInputDto: CreateInputReq) {
console.log(`/input`, 'ON CREATE ROUTE');
const inputService = new InputsService(this.inputsClientService);
const response = await inputService.create(createInputDto);
const response = await this.inputService.create(createInputDto);
return response;
}
@Post(':id')
@ApiOkResponse({ type: Input })
async reCreate(@Param('id') id: string, @Body() input: CreateInputReq) {
if (!input.id) input.id = id;
console.log(`POST /${input.id}`, 'ON RECREATE ROUTE');
const response = await this.inputService.reCreate(input);
return response;
}
@@ -81,9 +89,7 @@ export class InputsController {
async findAll(@Body() body) {
console.log(`/input`, 'ON FIND ALL ROUTE');
const inputService = new InputsService(this.inputsClientService);
const response = await inputService.findAll(body);
const response = await this.inputService.findAll(body);
return response;
}
@@ -92,9 +98,8 @@ export class InputsController {
async findOne(@Body() body, @Param() params) {
const { id } = params;
console.log(`/input/${id}`, 'ON FIND ONE ROUTE');
const inputService = new InputsService(this.inputsClientService);
const response = await inputService.findOne({ id, ...body });
const response = await this.inputService.findOne({ id, ...body });
return response;
}
@@ -106,9 +111,8 @@ export class InputsController {
delete updateInputDto.info;
console.log(`/input/${id}`, 'ON UPDATE ROUTE');
const inputService = new InputsService(this.inputsClientService);
const response = await inputService.update(id, updateInputDto, info);
const response = await this.inputService.update(id, updateInputDto, info);
return response;
}
@@ -119,9 +123,7 @@ export class InputsController {
console.log(`/input/${id}`, 'ON DELETE ROUTE');
const inputService = new InputsService(this.inputsClientService);
const response = await inputService.remove({ id, ...data });
const response = await this.inputService.remove({ id, ...data });
return response;
}
+7
View File
@@ -75,6 +75,13 @@ export class InputsService {
const adjustedInput = this.adjustInputPayload(response.input);
return { ...response, input: adjustedInput };
}
async reCreate(data) {
const { info, cron } = data;
if (cron) this.validateCron({ info, cron });
const response = await this.inputClient.createGeneric(data);
const adjustedInput = this.adjustInputPayload(response.input);
return { ...response, input: adjustedInput };
}
async getAvailableEntities(data): Promise<{ entities: string[] }> {
return await this.inputClient.getAvailableEntities(data);
}
+38 -4
View File
@@ -1,20 +1,54 @@
import { Controller, Get, Req, UseGuards } from '@nestjs/common';
import {
BadRequestException,
Controller,
Get,
Query,
Redirect,
Req,
UseGuards,
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { AuthGuard } from '@nestjs/passport';
import { InputsClientService } from 'src/clients/inputs/client.service';
import { InputsService } from '../inputs/inputs.service';
@ApiTags('oauth')
@Controller('oauth')
export class OauthController {
inputService: InputsService;
frontendRedirectUri = '';
constructor(private inputsClientService: InputsClientService) {
this.inputService = new InputsService(this.inputsClientService);
switch (process.env.ENV) {
case 'dev':
case 'stg':
this.frontendRedirectUri = `https://app.${process.env.ENV}.dadosfera.ai/auth-callback`;
break;
case 'prd':
this.frontendRedirectUri = `https://app.dadosfera.ai/auth-callback`;
break;
default:
this.frontendRedirectUri = `http://localhost:4200/coletix/auth-callback`;
}
}
@UseGuards(AuthGuard('hubspot'))
@Get('hubspot')
async oauthHubspot(@Req() req) {
console.log(req);
return true;
}
@UseGuards(AuthGuard('hubspot'))
@Get('hubspot/callback')
async oauthHubspotCallback() {
console.log('hubspot/callback');
@Redirect()
async oauthHubspotCallback(@Req() req, @Query('state') customer_id) {
const { authInfo } = req;
if (!authInfo) throw new BadRequestException('Oauth tokens not found');
const { accessToken, refreshToken } = authInfo;
const response = await this.inputService.create({
info: { customer_id, customer: 'customer', user_id: 'empty' },
plugin: 'hubspot',
credentials: { access_token: accessToken, refresh_token: refreshToken },
});
return { url: `${this.frontendRedirectUri}?input_id=${response.input.id}` };
}
}
@@ -1,16 +1,20 @@
import { Strategy } from 'passport-hubspot-oauth2';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import { OauthSecrets } from 'src/utils/OauthSecrets';
@Injectable()
export class HubspotStrategy extends PassportStrategy(Strategy) {
constructor() {
constructor(
@Inject('OAUTH_SECRETS')
private readonly oauthSecrets: OauthSecrets,
) {
super(
{
clientID: 'c51bc9c9-e81c-4263-887e-7cc68ab8e185',
clientSecret: '99a8bb9d-b622-4ea7-a46c-77b74f98ce80',
callbackURL: 'http://localhost:3333/oauth/hubspot/callback',
redirectUri: 'http://localhost:3333/oauth/hubspot/callback',
clientID: oauthSecrets.hubspot.client_id,
clientSecret: oauthSecrets.hubspot.client_secret,
callbackURL: oauthSecrets.hubspot.redirect_uri,
redirectUri: oauthSecrets.hubspot.redirect_uri,
scope:
'automation business-intelligence oauth forms integration-sync sales-email-read crm.lists.read crm.objects.contacts.read crm.schemas.contacts.read crm.objects.companies.read crm.objects.deals.read crm.schemas.companies.read crm.schemas.deals.read crm.objects.owners.read crm.objects.quotes.read crm.schemas.quotes.read crm.objects.line_items.read crm.schemas.line_items.read',
passReqToCallback: true,
@@ -22,7 +26,8 @@ export class HubspotStrategy extends PassportStrategy(Strategy) {
}
authenticate(req, options) {
options.state = 'customer_id';
const { customer_id } = req.query;
options.state = customer_id;
super.authenticate(req, options);
}
}
+16 -14
View File
@@ -8,22 +8,24 @@ class OauthSecretsObject {
client_secret = '';
redirect_uri = '';
}
export class OauthScrets {
// @Injectable()
export class OauthSecrets {
hubspot = new OauthSecretsObject();
google = new OauthSecretsObject();
mailchimp = new OauthSecretsObject();
async init() {
const path = process.env.SM_OAUTH_PATH;
const secretsManagerClient = new SecretsManagerClient({});
for (const key in this) {
const getSecretComand = new GetSecretValueCommand({
SecretId: `${path}/${key}`,
});
const res = await secretsManagerClient
.send(getSecretComand)
.catch(() => null);
if (res) this[key] = JSON.parse(res.SecretString);
}
}
export async function getOauthSecrets() {
const secrets = new OauthSecrets();
const path = process.env.SM_OAUTH_PATH;
const secretsManagerClient = new SecretsManagerClient({});
for (const key in secrets) {
const getSecretComand = new GetSecretValueCommand({
SecretId: `${path}/${key}`,
});
const res = await secretsManagerClient
.send(getSecretComand)
.catch(() => null);
if (res) secrets[key] = JSON.parse(res.SecretString);
}
return secrets;
}
+1 -1
View File
File diff suppressed because one or more lines are too long