Lambda Validators provide a greater level of flexibility than JSON Schema Validators given you have the freedom to write code to perform whatever level of validation you want on your Configuration Document. JSON Schema Validators are limited to the valdations specified in the JSON Schema version 4.x specification.
In this section of the lab, we will perform a simple data type validation on one of the properties in our configuration document - intResultLimit
. We will create a Lambda to use for validation, assign AppConfig permissions to invoke the Lambda when AppConfig deployment is initiated and then test our Lambda Validation. Our tests will include first a negative test so that you can observe the behavior when the Lambda Validation fails and a second successful test that allows the deployment to continue.
Use the following procedure to create a Lambda Validator.
In order for AppConfig to be able to invoke the Lambda Validator, we must first create a resource-based policy to specifically allow the AppConfig service to invoke the AppConfigLabLambdaValidator we just created. We will do this through the AWS CLI using the aws lambda add-permission
command.
Use the following procedure to create a resource-based policy.
aws lambda add-permission --function-name AppConfigLabLambdaValidator --action lambda:InvokeFunction --statement-id appconfig --principal appconfig.amazonaws.com --output json --region us-east-1
Note that we are granting permissions for the AppConfig service to invoke the AppConfigLabLambdaValidator specifically.
Use the following procedure to add validation code to the Lambda Validator.
exports.handler = async (event, context) => {
try {
console.log('Received event:', JSON.stringify(event, null, 2));
/* Received event:
{
"content": "ewogICJib29sRW5hYmxlTGltaXRSZXN1bHRzIjogZmFsc2UsCiAgImludFJlc3VsdExpbWl0IjogMCwKICAiYm9vbEVuYWJsZUZpbHRlcmluZyI6IHRydWUKfQ==",
"uri": "arn:aws:lambda:us-east-1:xxxxx:function:AppConfigLabLambdaValidator"
}
*/
const data = JSON.parse(Buffer.from(event.content, 'base64').toString('ascii'));
console.log('Configuration Data: ', data);
/* Configuration data
{
boolEnableLimitResults: false,
intResultLimit: 0
}
*/
Object.keys(data).forEach(function (item) {
console.log('key: ',item); // key
console.log('value: ', data[item]); // value
const dataType = typeof data[item];
console.log('Data type: ', dataType);
if (item === 'intResultLimit' && dataType !== 'string')
throw new TypeError(`Configuration property ${item} configured as type ${dataType}; expecting type string`);
});
} catch(err) {
throw err;
}
};
Note that the code above incorrectly attempts to validate the intResultLimit
property as a type string
. This is intentional and will allow us to perform a negative test of our code initially as well as observe in CloudWatch logs the console.log
output to demonstrate the structure of the event received by the lambda from AppConfig.
In order to utilize the Lambda to validate our AppConfig Configuration Document, we will need to add a Lambda Validator to our Configuration Profile.
Use the following procedure to add a Lambda Validator to the AppConfig Configuration Profile.
Next, we will deploy our updated configuration profile that now has the Lambda Validator attached. Remember, our Lambda function code has a check within it to validate that the intResultLimit
property is a type string
. In our configuration document, the intResultLimit
property is set to 1
as a number type. When we attempt to deploy our function, the deployment will fail as a result.
Use the following procedure to redeploy our configuration profile to development and negative test the Lambda Validator.
Next, we will correct our Lambda Validator code so that the deployment will succeed and redeploy.
Use the following procedures to update the Lambda code and redeploy.
if (item === 'intResultLimit' && dataType !== 'string')
intResultLimit
is a number
type.
if (item === 'intResultLimit' && dataType !== 'number')