Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated Capture/Viewer Nodes to pull config files from Param Store #79

Merged
merged 4 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cdk-lib/capture-stacks/capture-bucket-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as kms from 'aws-cdk-lib/aws-kms';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as ssm from 'aws-cdk-lib/aws-ssm';

import * as plan from '../core/capacity-plan';
import * as plan from '../core/context-types';
import { ProductStack } from 'aws-cdk-lib/aws-servicecatalog';


Expand Down
16 changes: 13 additions & 3 deletions cdk-lib/capture-stacks/capture-nodes-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ import * as path from 'path'
import { Construct } from 'constructs';

import * as constants from '../core/constants';
import * as plan from '../core/capacity-plan';
import * as plan from '../core/context-types';
import {ClusterSsmValue} from '../core/ssm-wrangling';
import * as user from '../core/user-config';
import * as types from '../core/context-types';

export interface CaptureNodesStackProps extends cdk.StackProps {
readonly arkimeFilesMap: types.ArkimeFilesMap;
readonly captureBucket: s3.Bucket;
readonly captureBucketKey: kms.Key;
readonly captureVpc: ec2.Vpc;
Expand All @@ -30,7 +31,7 @@ export interface CaptureNodesStackProps extends cdk.StackProps {
readonly osPassword: secretsmanager.Secret;
readonly planCluster: plan.ClusterPlan;
readonly ssmParamNameCluster: string;
readonly userConfig: user.UserConfig;
readonly userConfig: types.UserConfig;
}

export class CaptureNodesStack extends cdk.Stack {
Expand Down Expand Up @@ -141,6 +142,13 @@ export class CaptureNodesStack extends cdk.Stack {
resources: [ksmEncryptionKey.keyArn]
}),
);
taskDefinition.addToTaskRolePolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['ssm:GetParameter'], // Container pulls configuration from Parameter Store
resources: [`arn:aws:ssm:${this.region}:${this.account}:parameter*`]
}),
);
props.osPassword.grantRead(taskDefinition.taskRole);
props.captureBucket.grantReadWrite(taskDefinition.taskRole);
props.captureBucketKey.grantEncryptDecrypt(taskDefinition.taskRole);
Expand All @@ -157,6 +165,8 @@ export class CaptureNodesStack extends cdk.Stack {
image: ecs.ContainerImage.fromAsset(path.resolve(__dirname, '..', '..', 'docker-capture-node')),
logging: new ecs.AwsLogDriver({ streamPrefix: 'CaptureNodes', mode: ecs.AwsLogDriverMode.NON_BLOCKING }),
environment: {
'ARKIME_CONFIG_INI_LOC': props.arkimeFilesMap.captureIniLoc,
'ARKIME_ADD_FILE_LOCS': JSON.stringify(props.arkimeFilesMap.captureAddFileLocs),
'AWS_REGION': this.region, // Seems not to be defined in this container, strangely
'BUCKET_NAME': props.captureBucket.bucketName,
'CLUSTER_NAME': props.clusterName,
Expand Down
2 changes: 1 addition & 1 deletion cdk-lib/capture-stacks/capture-vpc-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as logs from 'aws-cdk-lib/aws-logs';
import { Stack, StackProps } from 'aws-cdk-lib';

import * as plan from '../core/capacity-plan';
import * as plan from '../core/context-types';

export interface CaptureVpcStackProps extends StackProps {
readonly planCluster: plan.ClusterPlan;
Expand Down
2 changes: 1 addition & 1 deletion cdk-lib/capture-stacks/opensearch-domain-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {Domain, EngineVersion, TLSSecurityPolicy} from 'aws-cdk-lib/aws-opensear
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
import * as ssm from 'aws-cdk-lib/aws-ssm';

import * as plan from '../core/capacity-plan';
import * as plan from '../core/context-types';


export interface OpenSearchDomainStackProps extends StackProps {
Expand Down
2 changes: 2 additions & 0 deletions cdk-lib/cloud-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ switch(params.type) {

const captureNodesStack = new CaptureNodesStack(app, params.nameCaptureNodesStack, {
env: env,
arkimeFilesMap: params.arkimeFileMap,
captureBucket: captureBucketStack.bucket,
captureBucketKey: captureBucketStack.bucketKey,
captureVpc: captureVpcStack.vpc,
Expand All @@ -60,6 +61,7 @@ switch(params.type) {

const viewerNodesStack = new ViewerNodesStack(app, params.nameViewerNodesStack, {
env: env,
arkimeFilesMap: params.arkimeFileMap,
arnViewerCert: params.nameViewerCertArn,
captureBucket: captureBucketStack.bucket,
viewerVpc: captureVpcStack.vpc,
Expand Down
9 changes: 5 additions & 4 deletions cdk-lib/core/command-params.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as plan from './capacity-plan';
import * as user from './user-config';
import * as types from './context-types';

/**
* Base type for receiving arguments from the Python side of the app. These directly match the interface on the Python
Expand All @@ -13,6 +12,7 @@ export interface CommandParamsRaw { }
*/
export interface ClusterMgmtParamsRaw extends CommandParamsRaw {
type: 'ClusterMgmtParamsRaw';
arkimeFileMap: string;
nameCluster: string;
nameCaptureBucketStack: string;
nameCaptureBucketSsmParam: string;
Expand Down Expand Up @@ -78,6 +78,7 @@ export interface DestroyDemoTrafficParams extends CommandParams {
*/
export interface ClusterMgmtParams extends CommandParams {
type: 'ClusterMgmtParams'
arkimeFileMap: types.ArkimeFilesMap;
nameCluster: string;
nameCaptureBucketStack: string;
nameCaptureBucketSsmParam: string;
Expand All @@ -91,8 +92,8 @@ export interface ClusterMgmtParams extends CommandParams {
nameViewerPassSsmParam: string;
nameViewerUserSsmParam: string;
nameViewerNodesStack: string;
planCluster: plan.ClusterPlan;
userConfig: user.UserConfig;
planCluster: types.ClusterPlan;
userConfig: types.UserConfig;
}

/**
Expand Down
21 changes: 21 additions & 0 deletions cdk-lib/core/capacity-plan.ts → cdk-lib/core/context-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,24 @@ export interface ClusterPlan {
osDomain: OSDomainPlan;
s3: S3Plan;
}

/**
* Structure to hold the user's input configuration
*/
export interface UserConfig {
expectedTraffic: number;
spiDays: number;
historyDays: number;
replicas: number;
pcapDays: number;
}

/**
* Structure to hold the mapping of Arkime files to their path in the data store
*/
export interface ArkimeFilesMap {
captureIniLoc: string;
captureAddFileLocs: string[];
viewerIniLoc: string;
viewerAddFileLocs: string[];
}
2 changes: 1 addition & 1 deletion cdk-lib/core/context-wrangling.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as cdk from 'aws-cdk-lib';
import * as plan from './capacity-plan';
import * as prms from './command-params';
import {CDK_CONTEXT_CMD_VAR, CDK_CONTEXT_REGION_VAR, CDK_CONTEXT_PARAMS_VAR, ManagementCmd} from './constants';

Expand Down Expand Up @@ -86,6 +85,7 @@ function validateArgs(args: ValidateArgs) : (prms.ClusterMgmtParams | prms.Deplo
type: 'ClusterMgmtParams',
awsAccount: args.awsAccount,
awsRegion: args.awsRegion,
arkimeFileMap: JSON.parse(rawClusterMgmtParamsObj.arkimeFileMap),
nameCluster: rawClusterMgmtParamsObj.nameCluster,
nameCaptureBucketStack: rawClusterMgmtParamsObj.nameCaptureBucketStack,
nameCaptureBucketSsmParam: rawClusterMgmtParamsObj.nameCaptureBucketSsmParam,
Expand Down
2 changes: 1 addition & 1 deletion cdk-lib/core/ssm-wrangling.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as plan from '../core/capacity-plan';
import * as plan from './context-types';
import * as user from '../core/user-config';

/**
Expand Down
10 changes: 0 additions & 10 deletions cdk-lib/core/user-config.ts

This file was deleted.

11 changes: 11 additions & 0 deletions cdk-lib/viewer-stacks/viewer-nodes-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
import * as ssm from 'aws-cdk-lib/aws-ssm';
import * as path from 'path'
import { Construct } from 'constructs';
import * as types from '../core/context-types';

export interface ViewerNodesStackProps extends cdk.StackProps {
readonly arkimeFilesMap: types.ArkimeFilesMap;
readonly arnViewerCert: string;
readonly captureBucket: s3.Bucket;
readonly viewerVpc: ec2.Vpc;
Expand Down Expand Up @@ -62,6 +64,13 @@ export class ViewerNodesStack extends cdk.Stack {
resources: [ksmEncryptionKey.keyArn]
}),
);
taskDefinition.addToTaskRolePolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['ssm:GetParameter'], // Container pulls configuration from Parameter Store
resources: [`arn:aws:ssm:${this.region}:${this.account}:parameter*`]
}),
);
props.osPassword.grantRead(taskDefinition.taskRole);
props.captureBucket.grantRead(taskDefinition.taskRole);
props.osDomain.grantReadWrite(taskDefinition.taskRole);
Expand All @@ -73,6 +82,8 @@ export class ViewerNodesStack extends cdk.Stack {
image: ecs.ContainerImage.fromAsset(path.resolve(__dirname, '..', '..', 'docker-viewer-node')),
logging: new ecs.AwsLogDriver({ streamPrefix: 'ViewerNodes', mode: ecs.AwsLogDriverMode.NON_BLOCKING }),
environment: {
'ARKIME_CONFIG_INI_LOC': props.arkimeFilesMap.viewerIniLoc,
'ARKIME_ADD_FILE_LOCS': JSON.stringify(props.arkimeFilesMap.viewerAddFileLocs),
'AWS_REGION': this.region, // Seems not to be defined in this container, strangely
'BUCKET_NAME': props.captureBucket.bucketName,
'CLUSTER_NAME': props.clusterName,
Expand Down
5 changes: 1 addition & 4 deletions docker-capture-node/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ENV DEBIAN_FRONTEND noninteractive

# Get required and quality-of-life utilities
RUN apt-get update && \
apt-get install -y --no-install-recommends wget curl ca-certificates unzip less mandoc man-db vim libmagic1 iproute2 dnsutils net-tools tcpdump
apt-get install -y --no-install-recommends wget curl ca-certificates unzip less mandoc man-db vim libmagic1 iproute2 dnsutils net-tools tcpdump jq

# Install the AWS CLI so we can pull passwords from AWS Secrets Manager at runtime
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
Expand All @@ -20,8 +20,5 @@ RUN wget -O arkime.deb https://s3.amazonaws.com/files.molo.ch/arkime-main_ubuntu
# Download the rir & oui files
RUN /opt/arkime/bin/arkime_update_geo.sh

COPY ./arkime_config.ini /opt/arkime/etc/config.ini
COPY ./default.rules /opt/arkime/etc/default.rules

COPY ./run_capture_node.sh /run_capture_node.sh
CMD ["/run_capture_node.sh"]
50 changes: 41 additions & 9 deletions docker-capture-node/run_capture_node.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set -e
echo "============================================================"
echo "Cluster: $CLUSTER_NAME"
echo "Role: Capture Node"
echo "Arkime Config INI Datastore Location: $ARKIME_CONFIG_INI_LOC"
echo "Arkime Additional File Datastore Locations: $ARKIME_ADD_FILE_LOCS"
echo "AWS Region: $AWS_REGION"
echo "Bucket Name: $BUCKET_NAME"
echo "LB Healthcheck Port: $LB_HEALTH_PORT"
Expand All @@ -13,22 +15,52 @@ echo "OpenSearch Secret Arn: $OPENSEARCH_SECRET_ARN"
echo "S3 Storage Class: $S3_STORAGE_CLASS"
echo "============================================================"

# Pull our configuration files from the cloud
function write_file_from_datastore() {
datastore_location=$1

# Retrieve our file from the cloud and account for wacky escaping
param_val=$(aws ssm get-parameter --name "$datastore_location" --query Parameter.Value)
corrected_string=$(echo "$param_val" | sed 's/\\\"/\"/g' | sed 's/\\\\/\\/g') # Remove extra escaping
corrected_string=$(echo "$corrected_string" | sed 's/^"//' | sed 's/"$//') # Remove starting/ending quotes

# Pull out the values we need
system_path=$(echo "$corrected_string" | jq -r '.system_path')
echo "System Path: $system_path" >&2
contents=$(echo "$corrected_string" | jq -r '.contents')

# Write the file to disk
echo -e "$contents" > "$system_path"

# Return the path to the calling context
echo "$system_path"
}

echo "$ARKIME_ADD_FILE_LOCS" | jq -r '.[]' | while IFS= read -r path; do
echo "Processing File in Datastore: $path"
full_file_path=$(write_file_from_datastore "$path")
echo "Written to: $full_file_path"
done

echo "Processing config.ini in Datastore: $ARKIME_CONFIG_INI_LOC"
config_ini_path=$(write_file_from_datastore "$ARKIME_CONFIG_INI_LOC")
echo "Written to: $config_ini_path"

# Pull configuration from ENV and AWS in order to set up our Arkime install. The ENV variables come from the Fargate
# Container definition. We perform some escaping of the our replacement strings for safety.
# See: https://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern
echo "Configuring /opt/arkime/etc/config.ini ..."
echo "Configuring $config_ini_path ..."
ESCAPED_ENDPOINT=$(printf '%s\n' "$OPENSEARCH_ENDPOINT" | sed -e 's/[\/&]/\\&/g')
sed -i'' "s/_ENDPOINT_/$ESCAPED_ENDPOINT/g" /opt/arkime/etc/config.ini
sed -i'' "s/_OS_ENDPOINT_/$ESCAPED_ENDPOINT/g" "$config_ini_path"

OPENSEARCH_PASS=$(aws secretsmanager get-secret-value --secret-id $OPENSEARCH_SECRET_ARN --output text --query SecretString)
BASE64_AUTH=$(echo -n "admin:$OPENSEARCH_PASS" | base64)
sed -i'' "s/_AUTH_/$BASE64_AUTH/g" /opt/arkime/etc/config.ini
sed -i'' "s/_OS_AUTH_/$BASE64_AUTH/g" "$config_ini_path"

sed -i'' "s/_BUCKET_/$BUCKET_NAME/g" /opt/arkime/etc/config.ini
sed -i'' "s/_HEALTH_PORT_/$LB_HEALTH_PORT/g" /opt/arkime/etc/config.ini
sed -i'' "s/_REGION_/$AWS_REGION/g" /opt/arkime/etc/config.ini
sed -i'' "s/_STORAGE_CLASS_/$S3_STORAGE_CLASS/g" /opt/arkime/etc/config.ini
echo "Successfully configured /opt/arkime/etc/config.ini"
sed -i'' "s/_PCAP_BUCKET_/$BUCKET_NAME/g" "$config_ini_path"
sed -i'' "s/_HEALTH_PORT_/$LB_HEALTH_PORT/g" "$config_ini_path"
sed -i'' "s/_AWS_REGION_/$AWS_REGION/g" "$config_ini_path"
echo "Successfully configured $config_ini_path"

echo "Testing connection/creds to OpenSearch domain $OPENSEARCH_ENDPOINT ..."
curl -u admin:$OPENSEARCH_PASS -X GET https://$OPENSEARCH_ENDPOINT:443
Expand All @@ -46,4 +78,4 @@ chown nobody /opt/arkime/raw # Unneeded when using S3 offload

# Start Arkime Capture
echo "Running Arkime Capture process ..."
/opt/arkime/bin/capture
/opt/arkime/bin/capture --config "$config_ini_path"
3 changes: 1 addition & 2 deletions docker-viewer-node/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ENV DEBIAN_FRONTEND noninteractive

# Get required and quality-of-life utilities
RUN apt-get update && \
apt-get install -y --no-install-recommends wget curl ca-certificates unzip less mandoc man-db vim libmagic1 iproute2 dnsutils net-tools tcpdump
apt-get install -y --no-install-recommends wget curl ca-certificates unzip less mandoc man-db vim libmagic1 iproute2 dnsutils net-tools tcpdump jq

# Install the AWS CLI so we can pull the OpenSearch Domain password from AWS Secrets Manager at runtime
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
Expand All @@ -16,7 +16,6 @@ RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2
RUN wget -O arkime.deb https://s3.amazonaws.com/files.molo.ch/arkime-main_ubuntu20_amd64.deb && \
apt-get install -y ./arkime.deb && \
rm -rf ./arkime.deb
COPY ./arkime_config.ini /opt/arkime/etc/config.ini

COPY ./run_viewer_node.sh /run_viewer_node.sh
CMD ["/run_viewer_node.sh"]
Loading