Soy nuevo en Nest.JS y aparentemente no entiendo cómo usar los observables, así que espero que puedan ayudar.
Básicamente, tengo un método que necesita: primero: iniciar sesión en la bóveda de hashicorp y devolver un token de cliente a través de una llamada http. segundo: si recibimos un token de la bóveda, verificamos que la solicitud contuviera una identificación de certificación, si no, tenemos que solicitar que se genere una nueva certificación. Lo que requiere el token_cliente de la bóveda.
El problema que tengo es que cuando llamo a la bóveda para obtener el token_cliente, no me lo devuelven a tiempo para poder usarlo para generar un nuevo certificado a través de una segunda llamada a la API.
¿Qué puedo hacer para poder usar client_token en el siguiente paso?
Aquí está el código para mi último intento:
Controlador:
@Controller('user') export class UserController { constructor(private readonly userService: UserService) {} @Post('getUserCert') async getUserCert(@Body() loginDto: vaultLoginReqDto) { return this.userService.getCertificate(loginDto); } }El controlador llama al método getCertificate:
getCertificate(loginDto: vaultLoginReqDto) { this.loginToVault(loginDto); if (this.vault_token) { if (loginDto.cert_id) { this.checkForExistingCert(loginDto); } else { this.generateNewCert(this.vault_token); } } else { throw new Error('User is not authorized to access Vault.'); } }El método de inicio de sesión:
loginToVault(loginDto: vaultLoginReqDto) { const url = 'http://vault:8200/v1/auth/jwt/login'; const payload: vaultLoginReqDto = { jwt: loginDto.jwt, role: loginDto.role, }; try { this.httpService .post(url, payload) .subscribe((res: AxiosResponse<vaultLoginResDto>) => { this.vault_token = res.data.auth.client_token; }); } catch (e) { this.throwError(e, url, 'Unable to login to vault'); } }el método del problema es el método generateNewCert. No está recibiendo el token_bóveda a tiempo.
generateNewCert(vault_token: string): Observable<string> { const url = `http://127.0.0.1:8200/v1/xxxx/xxxx/issue/reader`; const payload = { common_name: 'id.xxxx.com', }; const headers = { 'X-Vault-Token': vault_token, }; try { return this.httpService.post(url, payload, { headers: headers }).pipe( map((res: AxiosResponse<vaultGetCertResDto>) => { return res.data.data.certificate; }), ); } catch (e) { this.throwError(e, url); } }¡Agradezco la ayuda!
La forma más fácil de hacer que funcione es convertirlo a una Promesa para que pueda esperar el resultado.
loginToVault(loginDto: vaultLoginReqDto) { const url = 'http://vault:8200/v1/auth/jwt/login'; const payload = { jwt: loginDto.jwt, role: loginDto.role, }; return this.httpService .post(url, payload) .pipe( catchError(() => {/** ...handleError **/}), map((res) => { this.vault_token = res.data.auth.client_token; return this.vault_token; }), ) .toPromise() } Ahora, puede usar async / await en getCertificate
async getCertificate(loginDto: vaultLoginReqDto) { await this.loginToVault(loginDto); // or const vault_token = await this.loginToVault(loginDto) if (this.vault_token) { if (loginDto.cert_id) { this.checkForExistingCert(loginDto); } else { this.generateNewCert(this.vault_token); } } else { throw new Error('User is not authorized to access Vault.'); } }