All files / src/resolvers/hosts AsgHostResolver.ts

100% Statements 35/35
76.92% Branches 20/26
100% Functions 10/10
100% Lines 30/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62  3x       3x     3x         6x 6x       5x 4x 4x 4x 4x   1x         2x 2x   3x 2x 3x       2x   2x   2x   2x   2x 2x       2x 2x 2x 2x 2x 2x 3x 2x      
import { ConfigServiceClient } from "@aws-sdk/client-config-service";
import { ARN, parse } from "@aws-sdk/util-arn-parser";
import { FlowHost, FlowRuleGroup,  ResolvedFlowHost } from "../../FlowDefinitions";
import { LoggerFactory } from "../../logger-factory";
import { Logger } from "../../logger-type";
import { CloudResourceHostResolver } from "./CloudResourceHostResolver";
import { ASGInstances, PrivateAddress } from "./Types";
 
export class AsgHostResolver extends CloudResourceHostResolver {
    logger: Logger;
    constructor( loggerFactory: LoggerFactory,
         configServiceClient: ConfigServiceClient,
        defaultAggregatorName?: string) {
        super( configServiceClient, defaultAggregatorName);
        this.logger = loggerFactory.getLogger('AsgHostResolver');
    }
 
    canResolve(host: FlowHost): boolean {
        if (host.type === 'Arn') {
            const arn = parse(host.value);
            const canResolve = arn.service === 'autoscaling';
            this.logger.info(`arn  is resolvable => ${canResolve}`, arn);
            return canResolve;
        } else {
            return false;
        }
    }
 
    async resolve(host: FlowHost, ruleGroup?: FlowRuleGroup): Promise<ResolvedFlowHost> {
        const arn = parse(host.value);
        const results = await this.queryForASGInfo(host, ruleGroup);
 
        const allInstanceIds = results?.flatMap(r => r.configuration.instances).map(i => i.instanceId);
        const allInstancePriviteIps = await this.getAllInstanceIps(allInstanceIds, arn, ruleGroup);
        return { ...host, addresses: allInstancePriviteIps?.map(r => r.configuration.privateIpAddress) ?? [] };
    }
 
    private async queryForASGInfo(ruleObject: FlowHost, ruleGroup: FlowRuleGroup | undefined) {
        const configAdvancedQueryString = `SELECT configuration.instances WHERE resourceType='AWS::AutoScaling::AutoScalingGroup' AND resourceId = '${ruleObject.value}'`;
 
        this.logger.info(`query for ASG ${configAdvancedQueryString}`);
        
        const data = await this.queryAwsConfig(ruleGroup, configAdvancedQueryString);
        // public or private
        const results = data.Results?.map(r => <ASGInstances>JSON.parse(r));
 
        this.logger.info('resolveObject results', results);
        return results;
    }
 
    private async getAllInstanceIps(allInstanceIds: string[] | undefined, arn: ARN, ruleGroup: FlowRuleGroup | undefined) {
        const subQuery = "('" + allInstanceIds?.join("','") + "')";
        this.logger.info(`subQuery for instance ${subQuery}`);
        const queryForInstanceIps = `SELECT configuration.privateIpAddress WHERE resourceType = 'AWS::EC2::Instance' AND configuration.instanceId IN ${subQuery} AND accountId = ${arn.accountId} `;
        this.logger.info(`query for instance ${queryForInstanceIps}`);
        const associatedInstanceIpsData = await this.queryAwsConfig(ruleGroup, queryForInstanceIps);
        this.logger.info('query for instance response ', associatedInstanceIpsData);
        const allInstancePriviteIps = associatedInstanceIpsData.Results?.map(r => <PrivateAddress>JSON.parse(r));
        return allInstancePriviteIps;
    }
 
}