From 2bc060b13dcfa3734efe2e3a9fd2054a2fb69e71 Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Tue, 24 Jan 2023 19:19:00 -0300 Subject: [PATCH 01/10] FEAT: oauth sign in --- docsfera.json | 67 ++++++++++- package-lock.json | 14 +-- package.json | 2 +- src/modules/auth/auth.controller.ts | 107 +++++++++++++++++- src/modules/auth/auth.module.ts | 9 +- src/modules/auth/auth.service.ts | 9 ++ .../passport-strategies/google-strategy.ts | 46 ++++++++ src/utils/OauthSecrets.ts | 4 + src/utils/errorCodes.ts | 34 ++++++ 9 files changed, 281 insertions(+), 11 deletions(-) create mode 100644 src/modules/auth/passport-strategies/google-strategy.ts diff --git a/docsfera.json b/docsfera.json index f509fa0..7bc5522 100644 --- a/docsfera.json +++ b/docsfera.json @@ -288,6 +288,71 @@ ] } }, + "/auth/session/{session}": { + "get": { + "operationId": "AuthController_getSession", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Auth" + ] + } + }, + "/auth/oauth/google": { + "get": { + "operationId": "AuthController_googleOauth", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "boolean" + } + } + } + } + }, + "tags": [ + "Auth" + ] + } + }, + "/auth/oauth/google/callback": { + "get": { + "operationId": "AuthController_googleOauthCallback", + "parameters": [], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "Auth" + ] + } + }, "/connectors": { "post": { "operationId": "ConnectorController_uploadConnector", @@ -3405,7 +3470,7 @@ } }, "info": { - "title": "Maestro - feature/upload-to-s3-presigned", + "title": "Maestro - feat/oauth-login", "description": "Documentation for Maestro gateway", "version": "1.0.0", "contact": {} diff --git a/package-lock.json b/package-lock.json index 49a0c80..b97f6b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "dependencies": { "@aws-sdk/client-secrets-manager": "^3.112.0", "@dadosfera/dadosfera-logs": "^1.0.0-beta.4", - "@dadosfera/protospack-v2": "3.28.0", + "@dadosfera/protospack-v2": "3.29.0-beta.1", "@grpc/grpc-js": "^1.6.7", "@grpc/proto-loader": "^0.6.13", "@nestjs/common": "^8.4.7", @@ -1727,9 +1727,9 @@ } }, "node_modules/@dadosfera/protospack-v2": { - "version": "3.28.0", - "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.28.0.tgz", - "integrity": "sha512-JZYYhoaXFUpb5W/fBVt4XYe1Hlef2x9aLlM2Yv0erYn9QAu+/Pb99YnXbkgawQVlmJojSRrAvSwq1o9yOgKCrg==", + "version": "3.29.0-beta.1", + "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.29.0-beta.1.tgz", + "integrity": "sha512-V9Fe1+sZ36tsTXUo6OZ97eqeJGdQb9y5f/7OiUgaKnYClzDH6s85+8SLLlpXM8c6KR5dZVeZGAjTRfw9ZV2/jg==", "dependencies": { "@grpc/grpc-js": "^1.6.7", "rxjs": "^7.5.5", @@ -12284,9 +12284,9 @@ } }, "@dadosfera/protospack-v2": { - "version": "3.28.0", - "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.28.0.tgz", - "integrity": "sha512-JZYYhoaXFUpb5W/fBVt4XYe1Hlef2x9aLlM2Yv0erYn9QAu+/Pb99YnXbkgawQVlmJojSRrAvSwq1o9yOgKCrg==", + "version": "3.29.0-beta.1", + "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.29.0-beta.1.tgz", + "integrity": "sha512-V9Fe1+sZ36tsTXUo6OZ97eqeJGdQb9y5f/7OiUgaKnYClzDH6s85+8SLLlpXM8c6KR5dZVeZGAjTRfw9ZV2/jg==", "requires": { "@grpc/grpc-js": "^1.6.7", "rxjs": "^7.5.5", diff --git a/package.json b/package.json index 6525a77..d491e9b 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dependencies": { "@aws-sdk/client-secrets-manager": "^3.112.0", "@dadosfera/dadosfera-logs": "^1.0.0-beta.4", - "@dadosfera/protospack-v2": "3.28.0", + "@dadosfera/protospack-v2": "3.29.0-beta.1", "@grpc/grpc-js": "^1.6.7", "@grpc/proto-loader": "^0.6.13", "@nestjs/common": "^8.4.7", diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 2bf3915..8df8a58 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -8,6 +8,10 @@ import { Inject, UseFilters, Get, + UseGuards, + Redirect, + Req, + Param, } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { @@ -35,12 +39,17 @@ import { AuthSignInRes, } from './dtos/login'; import { PackTheMetadata } from 'src/utils/ PackTheMetadata'; +import { AuthGuard } from '@nestjs/passport'; +import { Request } from 'express'; +import ErrorCodes, { OauthErrors } from 'src/utils/errorCodes'; +import jwt from 'jsonwebtoken'; @ApiTags('Auth') @UseFilters(new GrpcToHttpExceptionFilter()) @Controller('auth') export class AuthController { logger: DadosferaLogger; + redirectUrl: string; constructor( @Inject(DadosferaLogger) @@ -48,6 +57,17 @@ export class AuthController { private authClient: AuthClientService, ) { this.logger = dadosferaLogger.logger; + + switch (process.env.ENV) { + case 'stg': + this.redirectUrl = `https://app.${process.env.ENV}.dadosfera.ai/auth/login`; + break; + case 'prd': + this.redirectUrl = `https://app.dadosfera.ai/auth/login`; + break; + default: + this.redirectUrl = `http://localhost:4200/auth/login`; + } } @Post('sign-in') @@ -204,8 +224,93 @@ export class AuthController { @Authenticated() @Get('verify-access-token') - @HttpCode(HttpStatus.OK) verifyAccessToken() { return { access_token_status: 'valid' }; } + + @Get('session/:session') + getSession(@Param('session') session: string) { + return this.authClient.getSession(session); + } + + @Get('oauth/google') + @UseGuards(AuthGuard('google-login')) + googleOauth() { + return true; + } + + @Get('oauth/google/callback') + @UseGuards(AuthGuard('google-login')) + @Redirect() + async googleOauthCallback(@Req() req) { + const { url, email, token, language } = await this.callback(req); + if (url.searchParams.get('error')) return { url: url.href }; + + await this.authClient + .oauthSignIn({ + username: email, + token, + }) + .then(({ session }) => { + url.searchParams.set('session', session); + }) + .catch((err) => { + let error = OauthErrors.INVALID_CREDENTIALS[language].error; + let error_description = + OauthErrors.INVALID_CREDENTIALS[language].error_description; + switch (err.details) { + case ErrorCodes.USER.NOT_FOUND: + error = OauthErrors.USER_NOT_FOUND[language].error; + error_description = + OauthErrors.USER_NOT_FOUND[language].error_description(email); + break; + case ErrorCodes.AUTH.UNAUTHORIZED: + error = OauthErrors.INVALID_SESSION[language].error; + error_description = + OauthErrors.INVALID_SESSION[language].error_description; + break; + } + url.searchParams.set('error', error); + url.searchParams.set('error_description', error_description); + return null; + }); + return { url: url.href }; + } + + async callback(req: Request) { + const { error, state } = req.query; + const { authInfo } = req; + const url = new URL(this.redirectUrl); + let email, token, error_title, error_description; + let language: 'pt-br' | 'en-us' = 'pt-br'; + + const stateObject = jwt.verify( + state as string, + process.env.JWT_PRIVATE_KEY, + ); + if (typeof stateObject != 'string') language = stateObject.language; + + if (error || !authInfo) { + this.logger.error(error); + if (!authInfo) this.logger.error('No authInfo', { request: req }); + + error_title = OauthErrors.INVALID_CREDENTIALS[language].error; + error_description = + OauthErrors.INVALID_CREDENTIALS[language].error_description; + if (error) error_description += ` - [${error}]`; + } else { + const { accessToken } = authInfo as any; + const { _json: userInfo } = req.user as any; + + email = userInfo.email; + token = accessToken; + } + + if (error_title) { + url.searchParams.set('error', error_title); + url.searchParams.set('error_description', error_description); + } + + return { token, email, url, language }; + } } diff --git a/src/modules/auth/auth.module.ts b/src/modules/auth/auth.module.ts index 1f6c3f4..24e7623 100644 --- a/src/modules/auth/auth.module.ts +++ b/src/modules/auth/auth.module.ts @@ -6,12 +6,19 @@ import { AuthController } from './auth.controller'; import { AuthClientService } from './auth.service'; import { DucClient } from '../duc/client.config'; +import { GoogleLoginStrategy } from './passport-strategies/google-strategy'; +import { getOauthSecrets } from 'src/utils/OauthSecrets'; const client = new DucClient(); @Module({ imports: [ClientsModule.register([client.providerOptions])], controllers: [AuthController], - providers: [AuthClientService, DadosferaLogger], + providers: [ + AuthClientService, + DadosferaLogger, + GoogleLoginStrategy, + { provide: 'OAUTH_SECRETS', useValue: getOauthSecrets() }, + ], exports: [AuthClientService], }) export class AuthModule {} diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts index 8a69efe..6db5c8c 100644 --- a/src/modules/auth/auth.service.ts +++ b/src/modules/auth/auth.service.ts @@ -157,4 +157,13 @@ export class AuthClientService implements OnModuleInit { this.authService.AuthVerifyTotpMfa({ accessToken, totp }), ); } + + async getSession(session: string) { + return lastValueFrom(this.authService.AuthGetSession({ session })); + } + + async oauthSignIn(data: { username: string; token: string }) { + const { username, token } = data; + return lastValueFrom(this.authService.AuthOauthSignIn({ token, username })); + } } diff --git a/src/modules/auth/passport-strategies/google-strategy.ts b/src/modules/auth/passport-strategies/google-strategy.ts new file mode 100644 index 0000000..f290897 --- /dev/null +++ b/src/modules/auth/passport-strategies/google-strategy.ts @@ -0,0 +1,46 @@ +import { + AuthenticateOptionsGoogle, + Profile, + Strategy, + StrategyOptions, +} from 'passport-google-oauth20'; +import { PassportStrategy } from '@nestjs/passport'; +import { Inject, Injectable } from '@nestjs/common'; +import { OauthSecrets } from 'src/utils/OauthSecrets'; +import { Request } from 'express'; +import jwt from 'jsonwebtoken'; + +@Injectable() +export class GoogleLoginStrategy extends PassportStrategy( + Strategy, + 'google-login', +) { + redirect_uri: string; + constructor( + @Inject('OAUTH_SECRETS') + private readonly oauthSecrets: OauthSecrets, + ) { + const options: StrategyOptions = { + clientID: oauthSecrets['google-login'].client_id, + clientSecret: oauthSecrets['google-login'].client_secret, + callbackURL: oauthSecrets['google-login'].client_secret, + scope: ['email', 'profile', 'openid'], + }; + const verify = ( + accessToken: string, + refreshToken: string, + profile: Profile, + done, + ) => { + return done(null, profile, { accessToken, refreshToken }); + }; + + super(options, verify); + } + + authenticate(req: Request, options: AuthenticateOptionsGoogle) { + const language = req.headers['dadosfera-lang'] || req.query.language; + options.state = jwt.sign({ language }, process.env.JWT_PRIVATE_KEY); + super.authenticate(req, options); + } +} diff --git a/src/utils/OauthSecrets.ts b/src/utils/OauthSecrets.ts index d882c76..28b9f62 100644 --- a/src/utils/OauthSecrets.ts +++ b/src/utils/OauthSecrets.ts @@ -2,6 +2,7 @@ import { SecretsManagerClient, GetSecretValueCommand, } from '@aws-sdk/client-secrets-manager'; +let cachedSecrets: OauthSecrets; class OauthSecretsObject { client_id = ''; @@ -15,8 +16,10 @@ export class OauthSecrets { mailchimp = new OauthSecretsObject(); facebook = new OauthSecretsObject(); salesforce = new OauthSecretsObject(); + 'google-login' = new OauthSecretsObject(); } export async function getOauthSecrets() { + if (cachedSecrets) return cachedSecrets; const secrets = new OauthSecrets(); const path = process.env.SM_OAUTH_PATH; const secretsManagerClient = new SecretsManagerClient({}); @@ -37,5 +40,6 @@ export async function getOauthSecrets() { }; } } + cachedSecrets = secrets; return secrets; } diff --git a/src/utils/errorCodes.ts b/src/utils/errorCodes.ts index 19a9d22..871f006 100644 --- a/src/utils/errorCodes.ts +++ b/src/utils/errorCodes.ts @@ -89,3 +89,37 @@ const ErrorCodes = { }; export default ErrorCodes; + +export const OauthErrors = { + INVALID_CREDENTIALS: { + 'pt-br': { + error: 'Erro ao autorizar', + error_description: 'Credenciais inválidas. Tente novamente', + }, + 'en-us': { + error: 'Authorization Error', + error_description: 'Invalid credentials. Please try again', + }, + }, + USER_NOT_FOUND: { + 'pt-br': { + error: 'Erro ao autorizar', + error_description: (email) => `Usuário não existe na Dadosfera: ${email}`, + }, + 'en-us': { + error: 'Authorization Error', + error_description: (email) => + `User does not exist on Dadosfera: ${email}`, + }, + }, + INVALID_SESSION: { + 'pt-br': { + error: 'Erro ao autorizar', + error_description: 'Sessão inválida!', + }, + 'en-us': { + error: 'Authorization Error', + error_description: 'Invalid session!', + }, + }, +}; From 6d61d74d0c51c08c6a679e20302553ff6e2b53aa Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Wed, 25 Jan 2023 09:51:22 -0300 Subject: [PATCH 02/10] FIX: set google callback --- src/modules/auth/passport-strategies/google-strategy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/auth/passport-strategies/google-strategy.ts b/src/modules/auth/passport-strategies/google-strategy.ts index f290897..2af25cd 100644 --- a/src/modules/auth/passport-strategies/google-strategy.ts +++ b/src/modules/auth/passport-strategies/google-strategy.ts @@ -23,7 +23,7 @@ export class GoogleLoginStrategy extends PassportStrategy( const options: StrategyOptions = { clientID: oauthSecrets['google-login'].client_id, clientSecret: oauthSecrets['google-login'].client_secret, - callbackURL: oauthSecrets['google-login'].client_secret, + callbackURL: oauthSecrets['google-login'].redirect_uri, scope: ['email', 'profile', 'openid'], }; const verify = ( From 642bf462ad5461f098282fd5cf02c52d3a000f35 Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Thu, 26 Jan 2023 17:00:27 -0300 Subject: [PATCH 03/10] FIX: add fallback language to pt-br --- src/modules/auth/auth.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 8df8a58..30c93ec 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -243,7 +243,7 @@ export class AuthController { @UseGuards(AuthGuard('google-login')) @Redirect() async googleOauthCallback(@Req() req) { - const { url, email, token, language } = await this.callback(req); + const { url, email, token, language = 'pt-br' } = await this.callback(req); if (url.searchParams.get('error')) return { url: url.href }; await this.authClient From 161d1fa05dbd2bcf41fca4a577a2cb97e4a99db8 Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Mon, 30 Jan 2023 16:35:05 -0300 Subject: [PATCH 04/10] Added some logs --- src/modules/auth/auth.controller.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 30c93ec..e7682ac 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -236,6 +236,7 @@ export class AuthController { @Get('oauth/google') @UseGuards(AuthGuard('google-login')) googleOauth() { + this.logger.info('/oauth/google'); return true; } @@ -244,7 +245,10 @@ export class AuthController { @Redirect() async googleOauthCallback(@Req() req) { const { url, email, token, language = 'pt-br' } = await this.callback(req); - if (url.searchParams.get('error')) return { url: url.href }; + if (url.searchParams.get('error')) { + this.logger.error('/oauth/google - ERROR'); + return { url: url.href }; + } await this.authClient .oauthSignIn({ @@ -252,9 +256,11 @@ export class AuthController { token, }) .then(({ session }) => { + this.logger.info('/oauth/google - SUCESS'); url.searchParams.set('session', session); }) .catch((err) => { + this.logger.error('/oauth/google - ERROR'); let error = OauthErrors.INVALID_CREDENTIALS[language].error; let error_description = OauthErrors.INVALID_CREDENTIALS[language].error_description; From 52bf2bdef3514b0168bc184bf28a75833ad2a3af Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Tue, 31 Jan 2023 09:34:34 -0300 Subject: [PATCH 05/10] teste new docsfera cloud function url --- docsfera.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docsfera.json b/docsfera.json index 7bc5522..b16e704 100644 --- a/docsfera.json +++ b/docsfera.json @@ -3470,7 +3470,7 @@ } }, "info": { - "title": "Maestro - feat/oauth-login", + "title": "Maestro - teste new docsfera", "description": "Documentation for Maestro gateway", "version": "1.0.0", "contact": {} From 03c09a525b2ef6f9fa2e59a9d7de4344d7b0754f Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Wed, 1 Feb 2023 10:07:45 -0300 Subject: [PATCH 06/10] DOCS: documenting oauth flow --- docsfera.json | 2 +- src/modules/auth/README.md | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/modules/auth/README.md diff --git a/docsfera.json b/docsfera.json index b16e704..7bc5522 100644 --- a/docsfera.json +++ b/docsfera.json @@ -3470,7 +3470,7 @@ } }, "info": { - "title": "Maestro - teste new docsfera", + "title": "Maestro - feat/oauth-login", "description": "Documentation for Maestro gateway", "version": "1.0.0", "contact": {} diff --git a/src/modules/auth/README.md b/src/modules/auth/README.md new file mode 100644 index 0000000..02268dd --- /dev/null +++ b/src/modules/auth/README.md @@ -0,0 +1,38 @@ +# Auth + +## SSO/oAuth + +### Strategy +We are using [PassportJs](https://www.passportjs.org/) to handle oAuth authentications. + +When the client (front end) makes a `GET /auth/oauth/{strategy}` Passport automatically redirects the user to the `strategy` login page. To do that we must configure and use a **Passport Strategy**. We must also have a callback route, conventionally `GET /auth/oauth/{strategy}/callback`, so the oAuth app can report the status of the user's login. + +- If the oAuth is successfull we call DUC's `AuthOauthSignIn` request that gets the tokens from Cognito and saves them on cache temporarily under a key we call `session`. Duc returns that `session` to maestro which then redirects the user to our app login page with that `session` as a query param. + +- If the oAuth login is not successfull for some reason or the user **does not** exist on DUC's database we redirect the user to our login page with an `error` and `error_description` as query params. + +### Routes + +So in order to have an SSO login, besides configuring the Strategy, we must have two routes for each Strategy, like in the example below: + +```ts + @Get('oauth/google') + @UseGuards(AuthGuard('google-login')) + googleOauth() { + this.logger.info('/oauth/google'); + return true; + } + + @Get('oauth/google/callback') + @UseGuards(AuthGuard('google-login')) + @Redirect() + async googleOauthCallback(@Req() req) { + const { url, email, token, language = 'pt-br' } = await this.callback(req); + if (url.searchParams.get('error')) { + this.logger.error('/oauth/google - ERROR'); + return { url: url.href }; + } + // ... Rest of the logic + return { url: url.href }; + } +``` \ No newline at end of file From 52f17725afba23dc02a145db23abe1dd98114d4c Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Fri, 3 Feb 2023 15:03:51 -0300 Subject: [PATCH 07/10] new protospack version --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index b97f6b7..8cae407 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "dependencies": { "@aws-sdk/client-secrets-manager": "^3.112.0", "@dadosfera/dadosfera-logs": "^1.0.0-beta.4", - "@dadosfera/protospack-v2": "3.29.0-beta.1", + "@dadosfera/protospack-v2": "3.29.0", "@grpc/grpc-js": "^1.6.7", "@grpc/proto-loader": "^0.6.13", "@nestjs/common": "^8.4.7", @@ -1727,9 +1727,9 @@ } }, "node_modules/@dadosfera/protospack-v2": { - "version": "3.29.0-beta.1", - "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.29.0-beta.1.tgz", - "integrity": "sha512-V9Fe1+sZ36tsTXUo6OZ97eqeJGdQb9y5f/7OiUgaKnYClzDH6s85+8SLLlpXM8c6KR5dZVeZGAjTRfw9ZV2/jg==", + "version": "3.29.0", + "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.29.0.tgz", + "integrity": "sha512-G66u9V+/+5rQb+fpJdDXydTaji2Mlr0Ro5TTYcQleITKU9DjF1WZs/jP/Qu0Y224nCb8HhePvaVl/Rr0wtLt4w==", "dependencies": { "@grpc/grpc-js": "^1.6.7", "rxjs": "^7.5.5", @@ -12284,9 +12284,9 @@ } }, "@dadosfera/protospack-v2": { - "version": "3.29.0-beta.1", - "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.29.0-beta.1.tgz", - "integrity": "sha512-V9Fe1+sZ36tsTXUo6OZ97eqeJGdQb9y5f/7OiUgaKnYClzDH6s85+8SLLlpXM8c6KR5dZVeZGAjTRfw9ZV2/jg==", + "version": "3.29.0", + "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.29.0.tgz", + "integrity": "sha512-G66u9V+/+5rQb+fpJdDXydTaji2Mlr0Ro5TTYcQleITKU9DjF1WZs/jP/Qu0Y224nCb8HhePvaVl/Rr0wtLt4w==", "requires": { "@grpc/grpc-js": "^1.6.7", "rxjs": "^7.5.5", diff --git a/package.json b/package.json index d491e9b..4eaa62a 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dependencies": { "@aws-sdk/client-secrets-manager": "^3.112.0", "@dadosfera/dadosfera-logs": "^1.0.0-beta.4", - "@dadosfera/protospack-v2": "3.29.0-beta.1", + "@dadosfera/protospack-v2": "3.29.0", "@grpc/grpc-js": "^1.6.7", "@grpc/proto-loader": "^0.6.13", "@nestjs/common": "^8.4.7", From d06910515b5811c9ee11f979df2b16525cdb5c67 Mon Sep 17 00:00:00 2001 From: Gabriel Amorim Date: Fri, 10 Feb 2023 15:53:10 -0300 Subject: [PATCH 08/10] FIX: force deploy --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 7693260..ccb4f5b 100644 --- a/README.md +++ b/README.md @@ -299,4 +299,3 @@ Some technologies used in this project: ## ⚙️ Back-end Architecture The architecture can be found at [this link](https://sites.google.com/dadosfera.ai/wikidoproduto/time/back-end). - From d6b3e028900eb4a29bc5bcce14334505b7ef3733 Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Mon, 13 Feb 2023 10:30:50 -0300 Subject: [PATCH 09/10] FIX: automattically skip ssl when microservices connection are local --- docsfera.json | 2 +- src/modules/catalog/catalog-client.ts | 7 +++---- .../connection-test/connection-test-client.config.ts | 5 +++-- src/modules/connection/client.config.ts | 7 +++---- src/modules/connector/client.config.ts | 7 +++---- src/modules/pipelines/pipelines-client.ts | 7 +++---- src/modules/pipelinesV2/pipelines-client.ts | 7 +++---- src/modules/transformations/transformations-client.ts | 7 +++---- 8 files changed, 22 insertions(+), 27 deletions(-) diff --git a/docsfera.json b/docsfera.json index 7c3eb1f..0864d1a 100644 --- a/docsfera.json +++ b/docsfera.json @@ -3479,7 +3479,7 @@ } }, "info": { - "title": "Maestro - feat/oauth-login", + "title": "Maestro - main", "description": "Documentation for Maestro gateway", "version": "1.0.0", "contact": {} diff --git a/src/modules/catalog/catalog-client.ts b/src/modules/catalog/catalog-client.ts index bd58bdb..5d6208c 100644 --- a/src/modules/catalog/catalog-client.ts +++ b/src/modules/catalog/catalog-client.ts @@ -6,6 +6,8 @@ import { import { credentials } from '@grpc/grpc-js'; import { Catalog } from '@dadosfera/protospack-v2'; +const isLocalConnection = !!process.env.PIFACTORY_URL?.includes('0.0.0.0'); + export class CatalogClientConfiguration { public name = 'CatalogClientConfiguration'; private config: GrpcOptions = { @@ -16,10 +18,7 @@ export class CatalogClientConfiguration { Catalog.ProtoPackages.ReadPackage, Catalog.ProtoPackages.WritePackage, ], - credentials: - process.env.LOCAL_ENV || process.env.ENV === 'local' - ? undefined - : credentials.createSsl(), + credentials: isLocalConnection ? undefined : credentials.createSsl(), protoPath: [ Catalog.ProtoPaths.ReadFilePath, Catalog.ProtoPaths.WriteFilePath, diff --git a/src/modules/connection-test/connection-test-client.config.ts b/src/modules/connection-test/connection-test-client.config.ts index 4ef28bd..6c042c9 100644 --- a/src/modules/connection-test/connection-test-client.config.ts +++ b/src/modules/connection-test/connection-test-client.config.ts @@ -6,14 +6,15 @@ import { } from '@nestjs/microservices'; import { ConnectionTest } from '@dadosfera/protospack-v2'; +const isLocalConnection = !!process.env.INFACTORY_URL?.includes('0.0.0.0'); + export class ConnectionTestClientConfiguration { private config: GrpcOptions = { transport: Transport.GRPC, options: { url: process.env.INFACTORY_URL, package: [ConnectionTest.ProtoPackages.ReadPackage], - credentials: - process.env.ENV === 'local' ? undefined : credentials.createSsl(), + credentials: isLocalConnection ? undefined : credentials.createSsl(), protoPath: [ConnectionTest.ProtoPaths.ReadFilePath], loader: { keepCase: true, diff --git a/src/modules/connection/client.config.ts b/src/modules/connection/client.config.ts index 8f1cbb4..938ef37 100644 --- a/src/modules/connection/client.config.ts +++ b/src/modules/connection/client.config.ts @@ -6,6 +6,8 @@ import { } from '@nestjs/microservices'; import { ConnectionManager } from '@dadosfera/protospack-v2'; +const isLocalConnection = !!process.env.INFACTORY_URL?.includes('0.0.0.0'); + export class ConnectionClientConfiguration { public name = 'ConnectionClientConfiguration'; private config: GrpcOptions = { @@ -16,10 +18,7 @@ export class ConnectionClientConfiguration { ConnectionManager.ProtoPackages.WritePackage, ConnectionManager.ProtoPackages.ReadPackage, ], - credentials: - process.env.LOCAL_ENV || process.env.ENV === 'local' - ? undefined - : credentials.createSsl(), + credentials: isLocalConnection ? undefined : credentials.createSsl(), protoPath: [ ConnectionManager.ProtoPaths.WriteFilePath, ConnectionManager.ProtoPaths.ReadFilePath, diff --git a/src/modules/connector/client.config.ts b/src/modules/connector/client.config.ts index 711f265..fdbd5a1 100644 --- a/src/modules/connector/client.config.ts +++ b/src/modules/connector/client.config.ts @@ -6,6 +6,8 @@ import { } from '@nestjs/microservices'; import { ConnectorManager } from '@dadosfera/protospack-v2'; +const isLocalConnection = !!process.env.INFACTORY_URL?.includes('0.0.0.0'); + export class ConnectorClientConfiguration { public name = 'ConnectorClientConfiguration'; private config: GrpcOptions = { @@ -16,10 +18,7 @@ export class ConnectorClientConfiguration { ConnectorManager.ProtoPackages.WritePackage, ConnectorManager.ProtoPackages.ReadPackage, ], - credentials: - process.env.LOCAL_ENV || process.env.ENV === 'local' - ? undefined - : credentials.createSsl(), + credentials: isLocalConnection ? undefined : credentials.createSsl(), protoPath: [ ConnectorManager.ProtoPaths.WriteFilePath, ConnectorManager.ProtoPaths.ReadFilePath, diff --git a/src/modules/pipelines/pipelines-client.ts b/src/modules/pipelines/pipelines-client.ts index 1359ed5..a7055e7 100644 --- a/src/modules/pipelines/pipelines-client.ts +++ b/src/modules/pipelines/pipelines-client.ts @@ -6,6 +6,8 @@ import { import { PipelinePackages, PipelineProtoFilePath } from 'protospack'; import { credentials } from '@grpc/grpc-js'; +const isLocalConnection = !!process.env.PIFACTORY_URL?.includes('0.0.0.0'); + export class PipelinesClientConfiguration { public name = 'PipelinesClientConfiguration'; private config: GrpcOptions = { @@ -13,10 +15,7 @@ export class PipelinesClientConfiguration { options: { url: process.env.PIFACTORY_URL, package: PipelinePackages, - credentials: - process.env.LOCAL_ENV || process.env.ENV === 'local' - ? undefined - : credentials.createSsl(), + credentials: isLocalConnection ? undefined : credentials.createSsl(), protoPath: PipelineProtoFilePath, loader: { keepCase: true, diff --git a/src/modules/pipelinesV2/pipelines-client.ts b/src/modules/pipelinesV2/pipelines-client.ts index 0ddce5a..118e890 100644 --- a/src/modules/pipelinesV2/pipelines-client.ts +++ b/src/modules/pipelinesV2/pipelines-client.ts @@ -9,6 +9,8 @@ import { } from '@dadosfera/protospack-v2/dist/lib/PipelineV2'; import { credentials } from '@grpc/grpc-js'; +const isLocalConnection = !!process.env.PIFACTORY_URL?.includes('0.0.0.0'); + export class PipelinesClientConfiguration { public name = 'PipelinesClientConfiguration'; private config: GrpcOptions = { @@ -16,10 +18,7 @@ export class PipelinesClientConfiguration { options: { url: process.env.PIFACTORY_URL, package: [ProtoPackages.ReadPackage, ProtoPackages.WritePackage], - credentials: - process.env.LOCAL_ENV || process.env.ENV === 'local' - ? undefined - : credentials.createSsl(), + credentials: isLocalConnection ? undefined : credentials.createSsl(), protoPath: [ProtoPaths.ReadFilePath, ProtoPaths.WriteFilePath], loader: { keepCase: true, diff --git a/src/modules/transformations/transformations-client.ts b/src/modules/transformations/transformations-client.ts index 9be60ee..9b9a14d 100644 --- a/src/modules/transformations/transformations-client.ts +++ b/src/modules/transformations/transformations-client.ts @@ -6,6 +6,8 @@ import { import { credentials } from '@grpc/grpc-js'; import { Transformation } from '@dadosfera/protospack-v2'; +const isLocalConnection = !!process.env.INFACTORY_URL?.includes('0.0.0.0'); + export class TransformationsClientConfiguration { public name = 'TransformationsClientConfiguration'; private config: GrpcOptions = { @@ -13,10 +15,7 @@ export class TransformationsClientConfiguration { options: { url: process.env.INFACTORY_URL, package: [Transformation.ProtoPackages.WritePackage], - credentials: - process.env.LOCAL_ENV || process.env.ENV === 'local' - ? undefined - : credentials.createSsl(), + credentials: isLocalConnection ? undefined : credentials.createSsl(), protoPath: [Transformation.ProtoPaths.WriteFilePath], loader: { enums: String, From be64c582e1de2da396453b8b7800fee40a46b8eb Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Mon, 13 Feb 2023 12:03:28 -0300 Subject: [PATCH 10/10] Inject permissions more safe --- src/modules/permissions/permissions.service.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/permissions/permissions.service.ts b/src/modules/permissions/permissions.service.ts index f972a6b..f5a03a1 100644 --- a/src/modules/permissions/permissions.service.ts +++ b/src/modules/permissions/permissions.service.ts @@ -44,8 +44,11 @@ export class PermissionsService ); } - // internally used to send permissions to duc on microservice startup async onApplicationBootstrap() { + // Do not sent permissions if running local but pointing to a remote DUC url + if (process.env.ENV == 'local' && !process.env.DUC_URL.includes('0.0.0.0')) + return; + this.logger.info('sending permissions to DUC...'); const permissions = Object.values(PERMISSIONS_GROUPS).flatMap((namespace) =>