
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
CodePipeline में एक action के रूप में cfn_nag चलाने के लिए, आप AWS Serverless Application Repository के माध्यम से डिप्लॉय कर सकते हैं।
निष्पादित करने के लिए:
cfn_nag_scan --input-path <path to cloudformation json>
पथ एक डायरेक्टरी या कोई विशेष टेम्पलेट हो सकता है। यदि यह डायरेक्टरी है, तो सभी .json, .template, .yml और .yaml फ़ाइलें प्रोसेस की जाएंगी, जिसमें सबडायरेक्टरीज़ में रिकर्सिव रूप से जाना शामिल है।
डिफ़ॉल्ट आउटपुट प्रारूप फ्री-फॉर्म टेक्स्ट है, लेकिन --output-format json फ्लैग से 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 Workflow के भाग के रूप में चलाया जा सकता है।
अपनी GitHub Workflow फ़ाइल में, cfn_nag Action का उपयोग करने वाला एक step बनाएँ:
- name: Simple test
uses: stelligent/cfn_nag@master
with:
input_path: tests
GitHub Action के बारे में अधिक जानकारी यहाँ पाई जा सकती है।
cfn-nag 'profile' की अवधारणा का समर्थन करता है, जो प्रभावी रूप से लागू किए जाने वाले नियमों की अनुमति सूची (allow list) है। प्रोफ़ाइल एक टेक्स्ट फ़ाइल है जिसमें प्रति पंक्ति एक नियम पहचानकर्ता होना चाहिए। जब --profile-path कमांड लाइन तर्क के माध्यम से निर्दिष्ट किया जाता है, तो cfn-nag केवल उन विशेष नियमों से उल्लंघन लौटाएगा।
"profile" बनाने के पीछे की प्रेरणा यह है कि विभिन्न डेवलपर्स विभिन्न नियमों के बारे में चिंतित हो सकते हैं। उदाहरण के लिए, एक "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
यदि कोई ऐसा नियम है जिसे आप दबाना चाहते हैं, तो प्रभावित संसाधन में cfn_nag Metadata कुंजी जोड़ी जा सकती है ताकि cfn_nag को उस नियम के लिए विफलता या चेतावनी न बढ़ाने का निर्देश दिया जा सके।
उदाहरण के लिए, यदि आप एक सार्वजनिक-facing 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 डिप्लॉय समय पर पास किया जाता है।
पैरामीटर मानों की जाँच की अनुमति देने के लिए, एक उपयोगकर्ता --parameter-values-path=<filename/uri> फ्लैग के साथ कमांड लाइन पर cfn_nag और cfn_nag_scan दोनों को पारित JSON फ़ाइल में पैरामीटर मान निर्दिष्ट कर सकता है।
JSON का प्रारूप एक एकल कुंजी है, "Parameters", जिसका मान एक डिक्शनरी है जिसमें प्रत्येक कुंजी/मान जोड़ी Parameters में मैप होती है:
{
"Parameters": {
"Cidr": "0.0.0.0/0"
}
}
यह निम्नलिखित Parameter को "0.0.0.0/0" प्रदान करेगा:
Parameters:
Cidr:
Type: String
सावधान रहें कि यदि JSON में अतिरिक्त पैरामीटर हैं, तो उन्हें चुपचाप अनदेखा कर दिया जाता है (cfn_nag_scan को सभी टेम्पलेट्स पर समान JSON लागू करने की अनुमति देने के लिए)।
यदि JSON त्रुटिपूर्ण है या उपरोक्त विनिर्देशन को पूरा नहीं करता है, तो पार्सिंग FATAL उल्लंघन के साथ विफल हो जाएगी।
0.5.55 से पहले, Fn::FindInMap के कॉल प्रभावी रूप से अनदेखा कर दिए जाते थे। अंतर्निहित मॉडल उन्हें वैसे ही छोड़ देता था, और इसलिए वे नियमों के लिए Hash मान के रूप में दिखाई देते थे। उदाहरण के लिए: { "Fn::FindInMap" => [map1, key1, key2]}
0.5.55 से शुरू करते हुए, मॉडल FindInMap के कॉल के लिए मान की गणना करने का प्रयास करेगा और उस मान को नियमों के सामने प्रस्तुत करेगा। यह मूल्यांकन उन कुंजियों का समर्थन करता है जो:
यदि मूल्यांकन तर्क किसी कुंजी के लिए मान नहीं समझ पाता है, तो यह पूरी अभिव्यक्ति के लिए Hash लौटाने के पुराने व्यवहार पर वापस चला जाएगा।
इसके अलावा 0.5.55 से पहले, AWS स्यूडोफ़ंक्शंस के कॉल प्रभावी रूप से अनदेखा कर दिए जाते थे। अंतर्निहित मॉडल उन्हें वैसे ही छोड़ देता था, और इसलिए वे नियमों के लिए Hash मान के रूप में दिखाई देते थे। उदाहरण के लिए: {"Ref"=>"AWS::Region"}। एक सामान्य उपयोग मामला मैपिंग को क्षेत्र (region) के अनुसार व्यवस्थित करना है, इसलिए मैप मूल्यांकन को बेहतर समर्थन देने के लिए स्यूडोफ़ंक्शन मूल्यांकन महत्वपूर्ण है।
0.5.55 से शुरू करते हुए, मॉडल निम्नलिखित AWS स्यूडोफ़ंक्शंस को डिफ़ॉल्ट मानों के साथ नियमों के सामने प्रस्तुत करेगा:
'AWS::URLSuffix' => 'amazonaws.com',
'AWS::Partition' => 'aws',
'AWS::NotificationARNs' => '',
'AWS::AccountId' => '111111111111',
'AWS::Region' => 'us-east-1',
'AWS::StackId' => 'arn:aws:cloudformation:us-east-1:111111111111:stack/stackname/51af3dc0-da77-11e4-872e-1234567db123',
'AWS::StackName' => 'stackname'
इसके अतिरिक्त, अंतिम उपयोगकर्ता पारंपरिक पैरामीटर प्रतिस्थापन तंत्र के माध्यम से आपूर्ति किए गए मान को ओवरराइड कर सकता है। उदाहरण के लिए:
{
"Parameters": {
"AWS::Region": "eu-west-1"
}
}
cfn_nag के संस्करण 0.4.66 तक, अंतर्निहित मॉडल टेम्पलेट के भीतर Fn::If की कोई प्रोसेसिंग नहीं करता था। इसका मतलब था कि यदि किसी प्रॉपर्टी का सशर्त मान होता था, तो Fn::If को पार्स करना नियम पर निर्भर था। यह देखते हुए कि Fn::If लगभग कहीं भी प्रकट हो सकता था, इसने नियम डेवलपर्स के लिए एक वैक-ए-मोल (whack-a-mole) स्थिति पैदा कर दी। अधिक से अधिक, नियम तर्क उन मानों को अनदेखा कर सकता था जो Hash थे, यह मानते हुए कि मान पहले स्थान पर Hash नहीं था।
इस मुद्दे को हल करने के लिए, cfn_nag के लिए डिफ़ॉल्ट व्यवहार अब Fn::If को true परिणाम से प्रतिस्थापित करना है। इसका मतलब है कि डिफ़ॉल्ट रूप से नियम सुरक्षा उल्लंघनों के लिए false परिणामों का निरीक्षण नहीं करेंगे।
प्रॉपर्टी मान स्तर पर Fn::If को प्रतिस्थापित करने के अलावा, वही व्यवहार Properties के शीर्ष-स्तर पर Fn::If पर भी लागू होता है। उदाहरण के लिए:
Resource1:
Type: Foo
Properties: !If
- IsNone
- Description: Up
- Description: DOwn
निम्नलिखित जैसा ही दिखेगा:
Resource1:
Type: Foo
Properties:
Description: Up
इस व्यवहार पर कुछ नियंत्रण प्रदान करने के लिए, एक उपयोगकर्ता --condition-values-path=<filename/uri> फ्लैग के साथ कमांड लाइन पर cfn_nag और cfn_nag_scan दोनों को पारित JSON फ़ाइल में स्थिति मान निर्दिष्ट कर सकता है।
JSON का प्रारूप एक डिक्शनरी है जिसमें प्रत्येक कुंजी/मान जोड़ी Conditions में मैप होती है:
{
"Condition1": true,
"Condition2": false
}
SPCM का आधार ब्लॉग पोस्ट विचार प्रयोग: IAM पॉलिसी दस्तावेज़ों के लिए प्रस्तावित जटिलता मेट्रिक में वर्णित है।
cfn_nag के संस्करण 0.6.0 से शुरू:
spcm_scan CloudFormation टेम्पलेट्स की एक डायरेक्टरी को स्कैन कर सकता है (cfn_nag_scan की तरह) और SPCM मेट्रिक्स के साथ JSON या HTML प्रारूप में एक रिपोर्ट उत्पन्न कर सकता हैcfn_nag_scan --rule-arguments spcm_threshold:100--rule-arguments तंत्र के माध्यम से सेटिंग्स के लिए अंतिम उपयोगकर्ता मान स्वीकार करने हेतु नियम विकसित कर सकते हैं। Rule ऑब्जेक्ट को केवल attr_accessor घोषित करने की आवश्यकता है, जैसे attr_accessor :spcm_threshold, और cfn_nag --rule-arguments से मान इंजेक्ट करने का विवरण संभाल लेगा0.5.x का रिलीज़ इसमें प्रमुख परिवर्तन शामिल हैं कि कस्टम नियम कैसे वितरित और लोड किए जा (सकते) हैं। इस रिलीज़ से पहले, नियमों को लोड करने के दो स्थान थे: मुख्य cfn_nag gem के भीतर lib/cfn-nag/custom_rules डायरेक्टरी, और कमांड लाइन पर निर्दिष्ट कस्टम-रूल-डायरेक्टरी।
दो उपयोग मामले हैं जिन्होंने कस्टम नियमों को लोड करने के तरीके/स्थान के पुनः डिज़ाइन के लिए मजबूर किया। नियम लोडिंग तंत्र को सामान्यीकृत किया गया है ताकि कस्टम नियम रिपॉजिटरी का उपयोग नियमों की खोज के लिए किया जा सके।
फ़ाइल सिस्टम पर पड़े बहुत सारे "rule files" पारंपरिक सॉफ़्टवेयर विकास परिप्रेक्ष्य से अच्छे नहीं हैं। इन फ़ाइलों पर कोई संस्करण या ट्रेसेबिलिटी नहीं होती है, इसलिए 0.5.x एक "cfn_nag rule gem" की अवधारणा प्रस्तुत करता है। एक डेवलपर अलग gem के भाग के रूप में कस्टम नियम विकसित कर सकता है, उसे संस्करणित कर सकता है और इंस्टॉल कर सकता है... और उन नियमों को cfn_nag से संदर्भित किया जाता है जब तक gem मेटाडेटा में cfn_nag_rules => true शामिल होता है। "cfn-nag-hipaa-rules" जैसे नाम वाले gem के लिए, lib/cfn-nag-hipaa-rules के अंतर्गत कोई भी *.rb लोड किया जाएगा। किसी भी कस्टम नियम को cfn-nag/base_rule में CfnNag::BaseRule से व्युत्पन्न होना चाहिए (नहीं cfn-nag/custom-rules/base)। यदि नियम को किसी और चीज़ से व्युत्पन्न होना चाहिए, तो cfn_nag_rule? नामक एक विधि परिभाषित करना जो true लौटाती है, उसे भी एक नियम के रूप में लोड करने का कारण बनेगा।
जब cfn_nag AWS Lambda में चल रहा है - पारंपरिक अर्थों में वास्तव में कोई फ़ाइल सिस्टम नहीं होता है (/tmp के अलावा)। इसलिए, Lambda से केवल मुख्य नियम उपयोग योग्य होते हैं। कस्टम नियमों का समर्थन करने के लिए, cfn_nag फ़ाइल सिस्टम के बजाय S3 बकेट से नियमों की खोज का समर्थन करता है।
Ruby में कस्टम नियम विकसित करने के बारे में आपने जो कुछ भी देखा है, वह अभी भी सत्य है।
S3 बकेट से नियमों की खोज करने के लिए, इस सामग्री के साथ एक s3.yml फ़ाइल बनाएँ:
---
repo_class_name: S3BucketBasedRuleRepo
repo_arguments:
s3_bucket_name: cfn-nag-rules-my-enterprise
prefix: /rules
cfn-nag-rules-my-enterprise बकेट में /rules प्रीफ़िक्स (जैसे /rules/MyNewRule.rb) के साथ *Rule.rb फ़ाइलों को लागू करने के लिए, इस फ़ाइल को कमांड लाइन पर cfn_nag को इस प्रकार निर्दिष्ट करें:
cat my_cfn_template.yml | cfn_nag --rule-repository s3.yml
यदि नियम एक से अधिक बकेट में हैं, तो एकाधिक s3*.yml फ़ाइलें बनाएँ और उन्हें --rule-repository तर्क में निर्दिष्ट करें।
यदि परिवेशी AWS क्रेडेंशियल्स के पास cfn-nag-rules-enterprise बकेट तक पहुँचने की अनुमति है, तो यह /rules/*Rule.rb जैसे सभी नियम ढूंढ लेगा। यदि किसी विशेष aws_profile का उपयोग किया जाना चाहिए, तो इसे repo_arguments के अंतर्गत एक कुंजी के रूप में जोड़ें, जैसे aws_profile: my_aws_profile
फ़ाइल सिस्टम, gem इंस्टॉल और S3 के अलावा - नई वास्तुकला सैद्धांतिक रूप से DynamoDb, रिलेशनल डेटाबेस, या अन्य वेब सेवाओं से नियम लोड करने के लिए अन्य "rule repositories" विकसित करने का समर्थन करती है।
अपने स्वयं के उपयोग और/या सामुदायिक योगदान के लिए नए नियम लिखने हेतु, विवरण के लिए कस्टम नियम विकास देखें।
आरंभ से अंत तक TDD कस्टम नियम विकास प्रदर्शित करने वाला एक स्क्रीनकास्ट यहाँ उपलब्ध है:
https://www.youtube.com/watch?v=JRZct0naFd4&t=1601s
Specs चलाने के लिए, आपको यह सुनिश्चित करना होगा कि Docker इंस्टॉल है और cfn_nag निर्भरताएँ इस प्रकार इंस्टॉल हैं:
gem install bundle
bundle install
फिर, सभी specs चलाने के लिए, बस rake test:all चलाएँ।
एंड-टू-एंड परीक्षण चलाने के लिए, rake test:e2e चलाएँ। स्क्रिप्ट Gemfile में सभी gems को बंडल करेगी, cfn_nag gem को स्थानीय रूप से बनाकर इंस्टॉल करेगी, spec निर्भरताएँ इंस्टॉल करेगी, और फिर 'end_to_end' टैग किए गए परीक्षणों को निष्पादित करेगी। यह Amazon द्वारा प्रदान किए गए नमूना टेम्पलेट्स को भी डाउनलोड करेगी और उनके विरुद्ध cfn_nag_scan चलाएगी, ताकि यह देखा जा सके कि क्या कोई ज्ञात-अच्छे टेम्पलेट cfn-nag में अपवाद उत्पन्न करते हैं।
वर्तमान git शाखा को स्थानीय रूप से इंस्टॉल करने के लिए:
bundle install
scripts/deploy_local.sh
एक संपूर्ण रिमोट डेवलपमेंट वातावरण बनाया और सेट किया गया है, जिसमें नियम विकास और निर्माण में आसानी के लिए सभी उपकरण और सेटिंग्स पूर्व-कॉन्फ़िगर हैं। आप VS Code रिमोट डेवलपमेंट कार्यक्षमता का उपयोग करके इसे सक्षम कर सकते हैं।
Folder contains a dev container configuration file. Reopen folder to develop in a container, तो Reopen in Container बटन पर क्लिक करें[Dev Container] cfn_nag Development विकल्प का उपयोग करेंVS Code रिमोट डेवलपमेंट सेटअप के बारे में अधिक जानकारी यहाँ पाई जा सकती है, VS Code Remote Development।
बग की रिपोर्ट करने या फीचर का अनुरोध करने के लिए, GitHub रिपॉजिटरी के माध्यम से एक issue सबमिट करें: https://github.com/stelligent/cfn_nag/issues/new