
أداة فحص (Linting) لقوالب CloudFormation
تبحث أداة cfn-nag عن أنماط في قوالب CloudFormation قد تشير إلى بنية تحتية غير آمنة. بشكل تقريبي، ستبحث عن:
لمزيد من الخلفية حول الأداة، يرجى الاطلاع على هذا المنشور في مدونة Stelligent:
بافتراض تثبيت Ruby >= 2.5.x، يكون التثبيت مجرد:
gem install cfn-nag
على MacOS أو Linux يمكنك بدلاً من ذلك التثبيت عبر brew:
brew install ruby brew-gem
brew gem install cfn-nag
لتشغيل cfn_nag كإجراء في CodePipeline، يمكنك النشر عبر AWS Serverless Application Repository.
للتنفيذ:
cfn_nag_scan --input-path <path to cloudformation json>
يمكن أن يكون المسار دليلاً أو قالباً محدداً. إذا كان دليلاً، فستتم معالجة جميع ملفات .json, و .template و .yml و .yaml، بما في ذلك العودية إلى الأدلة الفرعية.
تنسيق الإخراج الافتراضي هو نص حر، ولكن يمكن اختيار إخراج json باستخدام العلم --output-format json.
اختيارياً، يقوم العلم --debug بإلقاء معلومات حول داخلية تحميل القواعد.
شغّل مع --help للحصول على قائمة كاملة بالمفاتيح المدعومة.
لرؤية قائمة بجميع القواعد التي يدعمها cfn-nag حالياً، توجد أداة سطر أوامر تقوم بإلقائها إلى stdout:
cfn_nag_rules
يتم توفير Dockerfile للراحة. وهو منشور على DockerHub باسم stelligent/cfn_nag.
https://hub.docker.com/r/stelligent/cfn_nag
يمكنك أيضاً بناؤه محلياً.
docker build -t stelligent/cfn_nag .
يمكنك تركيب دليل محلي يحتوي على قوالب داخل حاوية Docker ثم استدعاء cfn_nag في الحاوية. يستخدم هذا المثال قوالب الاختبار المستخدمة في اختبار الوحدات لـ cfn_nag:
$ docker run -v `pwd`/spec/test_templates:/templates -t stelligent/cfn_nag /templates/json/efs/filesystem_with_encryption.json
{
"failure_count": 0,
"violations": [
]
}
$ docker run -v `pwd`/spec/test_templates:/templates -t stelligent/cfn_nag /templates/json/efs/filesystem_with_no_encryption.json
{
"failure_count": 1,
"violations": [
{
"id": "F27",
"type": "FAIL",
"message": "EFS FileSystem should have encryption enabled",
"logical_resource_ids": [
"filesystem"
]
}
]
}
يمكن تشغيل cfn_nag_scan كجزء من سير عمل GitHub لتقييم الكود أثناء خطوط التكامل المستمر.
في ملف سير عمل GitHub الخاص بك، أنشئ خطوة تستخدم إجراء cfn_nag:
- name: Simple test
uses: stelligent/cfn_nag@master
with:
input_path: tests
مزيد من المعلومات حول إجراء GitHub تجدها هنا.
يدعم cfn-nag مفهوم "البروفايل" وهو عملياً قائمة سماح بالقواعد المطلوب تطبيقها. البروفايل هو ملف نصي يجب أن يحتوي على معرّف قاعدة واحد في كل سطر. عند تحديده عبر وسيط سطر الأوامر --profile-path، سيقوم cfn-nag بإرجاع المخالفات من تلك القواعد المحددة فقط.
الدافع وراء إنشاء "بروفايل" هو أن المطورين المختلفين قد يهتمون بقواعد مختلفة. على سبيل المثال، قد يهتم "infrastructure_developer" بقواعد IAM، بينما قد لا يتمكن "app_developer" من إنشاء موارد IAM وبالتالي لا يهتم بتلك القواعد.
فيما يلي مثال لبروفايل:
F1
F2
F27
W3
W5
قائمة الرفض هي عكس البروفايل بشكل أساسي: إنها قائمة بالقواعد التي لا يجب تطبيقها أبداً. عند تحديدها عبر وسيط سطر الأوامر --deny-list-path، لن يُرجع cfn-nag أبداً مخالفات من تلك القواعد المحددة في الملف.
في حال تم تحديد قاعدة في كليهما، ستأخذ قائمة الرفض الأولوية على البروفايل، ولن يتم تطبيق القاعدة.
التنسيق كما يلي. الحقلان البارزان الوحيدان هما RulesToSuppress وid لكل عنصر. لن يتم تفسير reason بواسطة cfn-nag، ولكن يُنصح بتبرير وتوثيق سبب عدم تطبيق القاعدة أبداً.
RulesToSuppress:
- id: W3
reason: W3 is something we never care about at enterprise X
في حال وجود قاعدة تريد كبتها، يمكن إضافة مفتاح Metadata خاص بـ cfn_nag إلى المورد المتأثر لإخبار cfn_nag بعدم إثارة فشل أو تحذير لتلك القاعدة.
على سبيل المثال، إذا كنت تقوم بإعداد ELB عام مواجه للجمهور ومفتوح للاتصالات الواردة من الإنترنت بموارد مثل التالية:
public_alb.yaml
# Partial template
PublicAlbSecurityGroup:
Properties:
GroupDescription: 'Security group for a public Application Load Balancer'
VpcId:
Ref: vpc
Type: AWS::EC2::SecurityGroup
PublicAlbSecurityGroupHttpIngress:
Properties:
CidrIp: 0.0.0.0/0
FromPort: 80
GroupId:
Ref: PublicAlbSecurityGroup
IpProtocol: tcp
ToPort: 80
Type: AWS::EC2::SecurityGroupIngress
سيقوم cfn_nag بإثارة تحذيرات مثل التالية:
$ cfn_nag_scan -i public_alb.yaml
------------------------------------------------------------
public_alb.yaml
------------------------------------------------------------------------------------------------------------------------
| WARN W9
|
| Resources: ["PublicAlbSecurityGroup"]
|
| Security Groups found with ingress cidr that is not /32
------------------------------------------------------------
| WARN W2
|
| Resources: ["PublicAlbSecurityGroup"]
|
| Security Groups found with cidr open to world on ingress. This should never be true on instance. Permissible on ELB
Failures count: 0
Warnings count: 2
بإضافة البيانات الوصفية، يمكن كبت هذه التحذيرات:
public_alb_with_suppression.yaml
# Partial template
PublicAlbSecurityGroup:
Properties:
GroupDescription: 'Security group for a public Application Load Balancer'
VpcId:
Ref: vpc
Type: AWS::EC2::SecurityGroup
Metadata:
cfn_nag:
rules_to_suppress:
- id: W9
reason: "This is a public facing ELB and ingress from the internet should be permitted."
- id: W2
reason: "This is a public facing ELB and ingress from the internet should be permitted."
PublicAlbSecurityGroupHttpIngress:
Properties:
CidrIp: 0.0.0.0/0
FromPort: 80
GroupId:
Ref: PublicAlbSecurityGroup
IpProtocol: tcp
ToPort: 80
Type: AWS::EC2::SecurityGroupIngress
$ cfn_nag_scan -i public_alb_with_suppression.yaml
------------------------------------------------------------
public_alb_with_supression.yaml
------------------------------------------------------------
Failures count: 0
Warnings count: 0
يمكن أن تمثل معلمات قالب CloudFormation مشكلة للتحليل الثابت لأن القيم تُحدد عند نقطة النشر. بعبارة أخرى، القيم غير متاحة عند إجراء التحليل الثابت - فالتحليل الثابت يمكنه فقط النظر إلى "الكود" الموجود أمامه. لذلك لن يتم الإبلاغ عن قاعدة دخول مجموعة أمان بقيمة 0.0.0.0/0 إذا كانت cidr معلمة وتم تمرير 0.0.0.0/0 في وقت النشر.
للسماح بفحص قيم المعلمات، يمكن للمستخدم تحديد قيم المعلمات في ملف JSON يتم تمريره عبر سطر الأوامر إلى كل من cfn_nag وcfn_nag_scan باستخدام العلم --parameter-values-path=<filename/uri>.
تنسيق JSON هو مفتاح واحد، "Parameters"، قيمته قاموس حيث يتوافق كل زوج مفتاح/قيمة مع المعلمات:
{
"Parameters": {
"Cidr": "0.0.0.0/0"
}
}
سيوفر هذا "0.0.0.0/0" للمعامل التالي:
Parameters:
Cidr:
Type: String