diff --git a/src/config.ts b/src/config.ts index 55f6a21d..bdd8daaa 100644 --- a/src/config.ts +++ b/src/config.ts @@ -19,6 +19,7 @@ const CONFIG_DEFAULTS: DatadogIntegrationDefaults = Object.freeze({ forwarderName: 'DatadogForwarder', forwarderVersion: 'latest', installDatadogPolicyMacro: true, + installDatadogForwarder: true, }); export type DatadogIntegrationConfigWithDefaults = DatadogIntegrationConfig & diff --git a/src/forwarder.ts b/src/forwarder.ts new file mode 100644 index 00000000..9b361433 --- /dev/null +++ b/src/forwarder.ts @@ -0,0 +1,53 @@ +import * as cfn from 'aws-cdk-lib/aws-cloudformation'; +import { Construct } from 'constructs'; + +export interface ForwarderStackProps extends Omit{ + forwarderVersion: string; + templateParameters: ForwarderTemplateParameters; +} + +export interface ForwarderTemplateParameters{ + /** + * The Datadog API key, which can be found from the APIs page (/account/settings#api). It will be stored in AWS Secrets Manager securely. If DdApiKeySecretArn is also set, this value will not be used. This value must still be set, however. + * @default 'USE_ARN' + */ + DdApiKey?: string; + + /** + * The ARN of the secret storing the Datadog API key, if you already have it stored in Secrets Manager. You still need to set a dummy value for "DdApiKey" to satisfy the requirement, though that value won't be used. + */ + DdApiKeySecretArn?: string; + + /** + * The Datadog Forwarder Lambda function name. DO NOT change when updating an existing CloudFormation stack, otherwise the current forwarder function will be replaced and all the triggers will be lost. + * @default DatadogForwarder + */ + FunctionName?: string; + + /** + * Define your Datadog Site to send data to. For the Datadog EU site, set to datadoghq.eu + * @default datadoghq.com + */ + DdSite?: string; +} +export class ForwarderStack extends cfn.CfnStack { + + constructor(scope: Construct, id: string, props: ForwarderStackProps) { + + const templateParams: ForwarderTemplateParameters = { + DdApiKey: 'USE_ARN', + DdApiKeySecretArn: props.templateParameters.DdApiKeySecretArn, + DdSite: props.templateParameters.DdSite, + FunctionName: props.templateParameters.DdSite, + ...props.templateParameters, + }; + + const templateParamsAsDict: { [key: string]: (string) } = Object.entries(templateParams) + .reduce((all, [key, value]) => ({ ...all, [key]: value.toString() }), {}); + + super(scope, id, { + templateUrl: `https://datadog-cloudformation-template.s3.amazonaws.com/aws/forwarder/${props.forwarderVersion}.yaml`, + parameters: templateParamsAsDict, + }); + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 476b6ae9..2605f006 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,7 @@ import { applyDefaultsToConfig, DatadogIntegrationConfigWithDefaults, } from './config'; +import * as forwarder from './forwarder'; import { bucketsToString } from './util'; type DatadogPermissionsLevel = 'Full' | 'Core'; @@ -63,6 +64,14 @@ export interface DatadogIntegrationConfig { */ readonly forwarderVersion?: string; + /** + * If you already deployed a stack using this template, or you want to deploy the ForwarderStack separately, set this parameter to false + * to skip the installation of the DatadogForwarder again + * + * @default true + */ + readonly installDatadogForwarder?: boolean; + /** * If you already deployed a stack using this template, set this parameter to false * to skip the installation of the DatadogPolicy Macro again @@ -93,9 +102,7 @@ export interface DatadogIntegrationConfig { * See https://datadog-cloudformation-template.s3.amazonaws.com/aws/forwarder/latest.yaml * for the latest parameters. */ - readonly additionalForwarderParams?: { - [key: string]: string; - }; + readonly additionalForwarderParams?: forwarder.ForwarderTemplateParameters; /** * Additional parameters to pass through to the underlying Integration Role CloudFormation @@ -127,7 +134,10 @@ export class DatadogIntegration extends Construct { } this.createIntegrationRole(propsWithDefaults, policyMacroStack); - this.createForwarderStack(propsWithDefaults); + + if (propsWithDefaults.installDatadogForwarder) { + this.createForwarderStack(propsWithDefaults); + } } private createPolicyMacroStack(): cfn.CfnStack { @@ -171,18 +181,17 @@ export class DatadogIntegration extends Construct { private createForwarderStack( props: DatadogIntegrationConfigWithDefaults, ): cfn.CfnStack { - return new cfn.CfnStack(this, 'ForwarderStack', { - templateUrl: `https://datadog-cloudformation-template.s3.amazonaws.com/aws/forwarder/${props.forwarderVersion}.yaml`, - parameters: Object.assign( - { - DdApiKey: 'USE_ARN', - DdApiKeySecretArn: props.apiKey.secretArn, - DdSite: props.site, - FunctionName: props.forwarderName, - }, - { ...props.additionalForwarderParams }, - ), - }); + + return new forwarder.ForwarderStack(this, 'ForwarderStack', { + forwarderVersion: props.forwarderVersion, + templateParameters: { + DdApiKey: 'USE_ARN', + DdApiKeySecretArn: props.apiKey.secretArn, + DdSite: props.site, + FunctionName: props.forwarderName, + ...props.additionalForwarderParams, + }, + } ); } } @@ -200,3 +209,5 @@ export class DatadogIntegrationStack extends cdk.Stack { new DatadogIntegration(this, id, props); } } + + diff --git a/test/index.test.ts b/test/index.test.ts index 07a4a215..4a705e67 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -407,7 +407,7 @@ describe('DatadogIntegrationStack', () => { apiKey: secret, externalId: 'not-a-real-id', additionalForwarderParams: { - Foo: 'bar', + FunctionName: 'bar', }, }); @@ -421,8 +421,7 @@ describe('DatadogIntegrationStack', () => { 'Fn::ImportValue': 'Stack:ExportsOutputRefSecretA720EF052D953DED', }, DdSite: 'datadoghq.com', - FunctionName: 'DatadogForwarder', - Foo: 'bar', // the sub-assert + FunctionName: 'bar', }, }); });