Skip to content

Commit

Permalink
Merge 4d4f859 into 3b80904
Browse files Browse the repository at this point in the history
  • Loading branch information
Nataniel López committed Mar 4, 2020
2 parents 3b80904 + 4d4f859 commit 6dbdeed
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 33 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -59,3 +59,6 @@ typings/

# next.js build output
.next

# VSCode
.vscode/
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Role assumption for authorizing the Firehose putRecord

## [3.0.0] - 2020-01-14
### Added
- Log struct and formatting
Expand Down
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -14,6 +14,7 @@ npm install @janiscommerce/log
### ENV variables
**`JANIS_SERVICE_NAME`** (required): The name of the service that will create the log.
**`JANIS_ENV`** (required): The name stage that will used as suffix for janis-trace-service bucket.
**`LOG_ROLE_ARN`** (required): The ARN to assume the trace role in order to put records in Firehose.

## API
### **`add(clientCode, log)`**
Expand Down
34 changes: 34 additions & 0 deletions lib/aws-wrappers.js
@@ -0,0 +1,34 @@
'use strict';

const { STS, Firehose } = require('aws-sdk');

class FirehoseWrapper {

constructor(config) {
this._firehose = new Firehose(config);
}

/* istanbul ignore next */
// AWS generates the Firehose class on the fly, the putRecord method do not exists before creating the insance
putRecord(record) {
return this._firehose.putRecord(record).promise();
}
}

class StsWrapper {

constructor(config) {
this._sts = new STS(config);
}

/* istanbul ignore next */
// AWS generates the STS class on the fly, the assumeRole method do not exists before creating the insance
assumeRole(params) {
return this._sts.assumeRole(params).promise();
}
}

module.exports = {
Firehose: FirehoseWrapper,
STS: StsWrapper
};
18 changes: 0 additions & 18 deletions lib/firehose-wrapper.js

This file was deleted.

3 changes: 2 additions & 1 deletion lib/log-error.js
Expand Up @@ -7,7 +7,8 @@ class LogError extends Error {
return {
INVALID_LOG: 1,
FIREHOSE_ERROR: 2,
NO_ENVIRONMENT: 3
NO_ENVIRONMENT: 3,
ASSUME_ROLE_ERROR: 4
};

}
Expand Down
60 changes: 55 additions & 5 deletions lib/log.js
Expand Up @@ -7,16 +7,15 @@ const UUID = require('uuid/v4');

const LogError = require('./log-error');

const Firehose = require('./firehose-wrapper');
const { STS, Firehose } = require('./aws-wrappers');

const ARN_DURATION = 1800; // 30 min
const MAX_ATTEMPTS = 3;
const MAX_TIMEOUT = 500;
const DELIVERY_STREAM_PREFIX = 'JanisTraceFirehose';

const firehose = new Firehose({
region: process.env.AWS_DEFAULT_REGION,
httpOptions: { timeout: MAX_TIMEOUT }
});
const sts = new STS();

const emitter = new EventEmmiter();

class Log {
Expand All @@ -29,6 +28,10 @@ class Log {
return process.env.JANIS_ENV;
}

static get _roleArn() {
return process.env.LOG_ROLE_ARN;
}

static get _envs() {

return {
Expand Down Expand Up @@ -121,6 +124,51 @@ class Log {
}
}

static async _getFirehoseInstance() {

const hasExpired = this._credentialsExpiration < new Date();

if(this._firehose && !hasExpired)
return this._firehose;

const firehoseParams = {
region: process.env.AWS_DEFAULT_REGION,
httpOptions: { timeout: MAX_TIMEOUT }
};

if(this._roleArn) {

firehoseParams.credentials = await this._getCredentials();

this._credentialsExpiration = firehoseParams.credentials.expiration;
}

this._firehose = new Firehose(firehoseParams);

return this._firehose;
}

static async _getCredentials() {

const assumedRole = await sts.assumeRole({
RoleArn: this._roleArn,
RoleSessionName: this._serviceName,
DurationSeconds: ARN_DURATION
});

if(!assumedRole)
throw new LogError('Failed to assume role, invalid response.', LogError.codes.ASSUME_ROLE_ERROR);

const { Credentials, Expiration } = assumedRole;

return {
accessKeyId: Credentials.AccessKeyId,
secretAccessKey: Credentials.SecretAccessKey,
sessionToken: Credentials.SessionToken,
expiration: Expiration
};
}

static _getFormattedEnv() {

if(this._env && this._envs[this._env])
Expand All @@ -133,6 +181,8 @@ class Log {

try {

const firehose = await this._getFirehoseInstance();

await firehose.putRecord({
DeliveryStreamName: this.deliveryStreamName,
Record: {
Expand Down

0 comments on commit 6dbdeed

Please sign in to comment.