Repository: chef/automate
Pull request #7797 (2023-03-30 17:12:25)

Verification and Reporting module
### :nut_and_bolt: Description: What code changed, and why?
Changes for Verification and Reporting module

```
chef-automate verify --help
Verify Chef Automate config files and Infrastructure

Usage:
  chef-automate verify [flags]

Flags:
      --certificates                Use this flag to verify the certificates provided in the file
      --file string                 Config file that needs to be verified
      --ha-aws-deploy               Use this flag to verify the AWS Deployment setup and config
      --ha-aws-managed-deploy       Use this flag to verify the AWS Deployment setup and config with Managed Services
      --ha-aws-managed-provision    Use this flag to verify the AWS Provision config with Managed services
      --ha-aws-provision            Use this flag to verify the AWS Provision config
      --ha-onprem-aws-deploy        Use this flag to verify the On-Premise setup and config with AWS Managed services
      --ha-onprem-customer-deploy   Use this flag to verify the On-Premise setup and config with Customer Managed services
      --ha-onprem-deploy            Use this flag to verify the On-Premise setup and config with Chef Managed services
  -h, --help                        help for verify
      --standalone-deploy           Use this flag to verify the Automate standalone setup and config

```
<!-- /!\ Please ensure that you are NOT disclosing any customer information without their consent /!\ -->

### :chains: Related Resources
Jira Tickets :- https://chefio.atlassian.net/browse/CHEF-1277
https://chefio.atlassian.net/browse/CHEF-835
### :+1: Definition of Done
- Created a Command for verification `chef-automate verify`
- Created a reporting module to print result if chef-automate verify command on terminal in tabular form

### :athletic_shoe: How to Build and Test the Change
- rebuild automate-cli
- start services in hab
- create a dummy OnPrem config for automate,chef-server,postgressql and opensearch ips
- run command `chef-automate verify --ha-onprem-deploy config.toml`

### :white_check_mark: Checklist

**All PRs** must tick these:

- [x] I have read the [CONTRIBUTING document](https://github.com/chef/automate/blob/master/CONTRIBUTING.md).
- [x] All commits signed-off for the [Developer Certification of Origin](https://github.com/chef/chef/blob/master/CONTRIBUTING.md#developer-certification-of-origin-dco).

With occasional exceptions, all PRs **from Progress employees** must tick these:

- [ ] Is the code clear? *(complicated code or lots of comments--subdivide and use well-named methods, meaningful variable names, etc.)*
- [ ] Consistency checked? *(user notifications, user prompts, visual patterns, code patterns, variable names)*
- [ ] Repeated code blocks eliminated? *(adapt and reuse existing components, blocks, functions, etc.)*
- [ ] Spelling, grammar, typos checked? *(at a minimum use `make spell` in any component directory)*
- [ ] Code well-formatted? *(indents, line breaks, etc. improve rather than hinder readability)*

All PRs **from Progress employees** should tick these if appropriate:

- [ ] Tests added/updated? (all new code needs new tests)
- [ ] Docs added/updated? (all customer-facing changes)

*Please add a note next to any checkbox above if you are NOT ticking it.*

### :camera: Screenshots, if applicable
[demo-for-verification-and-reporting](https://progresssoftware.sharepoint.com/:v:/s/ChefCoreC/EVWSLK6DMxtFsQ3p8GjX8E8BjgdBhEUTVauhKsOFcf70VA?e=lBH6TI)

netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *chef-automate* processing.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 53f78c9c85591766c733348ec040e0257259142a |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/chef-automate/deploys/6425c2fc4a2d230009ee9c70 |
sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [5 Code Smells](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![12.1%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '12.1%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [12.1% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![11.9%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/20-16px.png '11.9%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [11.9% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [10 Code Smells](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![53.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/50-16px.png '53.0%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [53.0% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![9.6%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/10-16px.png '9.6%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [9.6% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [6 Code Smells](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![52.7%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/50-16px.png '52.7%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [52.7% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![7.5%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/10-16px.png '7.5%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [7.5% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![E](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/E-16px.png 'E')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [1 Security Hotspot](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [1 Code Smell](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![52.7%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/50-16px.png '52.7%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [52.7% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![7.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/10-16px.png '7.4%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [7.4% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![E](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/E-16px.png 'E')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [1 Security Hotspot](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [1 Code Smell](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![52.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/50-16px.png '52.4%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [52.4% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![7.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/10-16px.png '7.4%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [7.4% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![50.6%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/50-16px.png '50.6%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [50.6% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/10-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [7.3% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![51.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/50-16px.png '51.0%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [51.0% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![9.5%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/10-16px.png '9.5%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [9.5% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [4 Code Smells](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![69.1%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/60-16px.png '69.1%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [69.1% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![9.1%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/10-16px.png '9.1%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [9.1% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![69.1%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/60-16px.png '69.1%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [69.1% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![9.1%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/10-16px.png '9.1%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [9.1% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=chef_automate&pullRequest=7797)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=chef_automate&pullRequest=7797&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=chef_automate&pullRequest=7797&resolved=false&types=CODE_SMELL)

[![68.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/60-16px.png '68.4%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list) [68.4% Coverage](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_coverage&view=list)  
[![9.1%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/10-16px.png '9.1%')](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list) [9.1% Duplication](https://sonarcloud.io/component_measures?id=chef_automate&pullRequest=7797&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/.bldr.toml b/.bldr.toml
index c58bc3ae0..6818e031d 100644
--- a/.bldr.toml
+++ b/.bldr.toml
@@ -440,6 +440,7 @@ paths = [
   "components/local-user-service/*",
   "lib/cereal/*",
   "lib/config/*",
+  "lib/config_parser/*",
   "lib/db/*",
   "lib/grpc/*",
   "lib/httputils/*",
@@ -452,12 +453,14 @@ paths = [
   "lib/proc/*",
   "lib/product/*",
   "lib/proxy/*",
+  "lib/reporting/*",
   "lib/secrets/*",
   "lib/stringutils/*",
   "lib/tls/*",
   "lib/tracing/*",
   "lib/user/*",
   "lib/uuid4/*",
+  "lib/verification/*",
   "lib/version/*"
 ]
 
diff --git a/.license_scout.yml b/.license_scout.yml
index afb17194a..7c2c789b4 100644
--- a/.license_scout.yml
+++ b/.license_scout.yml
@@ -329,6 +329,9 @@ fallbacks:
     - name: github.com/apparentlymart/go-textseg
       license_id: Unlicense
       license_content: https://github.com/apparentlymart/go-textseg/blob/master/LICENSE
+    - name: github.com/globalsign/mgo
+      license_id: Unlicense
+      license_content: https://github.com/globalsign/mgo/blob/master/LICENSE
 
   habitat:
     - name: chef/mlsa
diff --git a/components/automate-cli/cmd/chef-automate/verify.go b/components/automate-cli/cmd/chef-automate/verify.go
new file mode 100644
index 000000000..56e3c9f83
--- /dev/null
+++ b/components/automate-cli/cmd/chef-automate/verify.go
@@ -0,0 +1,223 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/chef/automate/components/automate-cli/pkg/docs"
+	"github.com/chef/automate/components/automate-cli/pkg/status"
+	verification "github.com/chef/automate/lib/verification"
+	"github.com/spf13/cobra"
+)
+
+type verifyCmdFlags struct {
+	file                      string
+	haAWSProvision            bool
+	haAWSManagedProvision     bool
+	haOnpremDeploy            bool
+	haOnPremAWSManagedDeploy  bool
+	haOnPremCustManagedDeploy bool
+	haAWSDeploy               bool
+	haAWSManagedDeploy        bool
+	standaloneDeploy          bool
+	certificates              bool
+}
+
+type verifyCmdFlow struct {
+	Verification      verification.Verification
+	A2HARBFileExist   bool
+	ManagedServicesOn bool
+}
+
+func init() {
+	flagsObj := verifyCmdFlags{}
+
+	verifyCmd := &cobra.Command{
+		Use:   "verify",
+		Short: "Verify Chef Automate setup",
+		Long:  "Verify Chef Automate config files and Infrastructure",
+		Annotations: map[string]string{
+			docs.Compatibility: docs.Compatibility,
+		},
+		Args: cobra.RangeArgs(0, 1),
+		RunE: verifyCmdFunc(&flagsObj),
+	}
+
+	// flags for Verify Command
+	verifyCmd.PersistentFlags().BoolVar(
+		&flagsObj.haAWSProvision,
+		"ha-aws-provision",
+		false,
+		"Use this flag to verify the AWS Provision config")
+	verifyCmd.PersistentFlags().BoolVar(
+		&flagsObj.haAWSManagedProvision,
+		"ha-aws-managed-provision",
+		false,
+		"Use this flag to verify the AWS Provision config with Managed services")
+	verifyCmd.PersistentFlags().BoolVar(
+		&flagsObj.haOnpremDeploy,
+		"ha-onprem-deploy",
+		false,
+		"Use this flag to verify the On-Premise setup and config with Chef Managed services")
+	verifyCmd.PersistentFlags().BoolVar(
+		&flagsObj.haOnPremAWSManagedDeploy,
+		"ha-onprem-aws-deploy",
+		false,
+		"Use this flag to verify the On-Premise setup and config with AWS Managed services")
+	verifyCmd.PersistentFlags().BoolVar(
+		&flagsObj.haOnPremCustManagedDeploy,
+		"ha-onprem-customer-deploy",
+		false,
+		"Use this flag to verify the On-Premise setup and config with Customer Managed services")
+	verifyCmd.PersistentFlags().BoolVar(
+		&flagsObj.haAWSDeploy,
+		"ha-aws-deploy",
+		false,
+		"Use this flag to verify the AWS Deployment setup and config")
+	verifyCmd.PersistentFlags().BoolVar(
+		&flagsObj.haAWSManagedDeploy,
+		"ha-aws-managed-deploy",
+		false,
+		"Use this flag to verify the AWS Deployment setup and config with Managed Services")
+	verifyCmd.PersistentFlags().BoolVar(
+		&flagsObj.standaloneDeploy,
+		"standalone-deploy",
+		false,
+		"Use this flag to verify the Automate standalone setup and config")
+	verifyCmd.PersistentFlags().BoolVar(
+		&flagsObj.certificates,
+		"certificates",
+		false,
+		"Use this flag to verify the certificates provided in the file")
+	verifyCmd.PersistentFlags().StringVar(
+		&flagsObj.file,
+		"file",
+		"",
+		"Config file that needs to be verified")
+	RootCmd.AddCommand(verifyCmd)
+}
+
+func verifyCmdFunc(flagsObj *verifyCmdFlags) func(cmd *cobra.Command, args []string) error {
+	return func(cmd *cobra.Command, args []string) error {
+		c := verifyCmdFlow{
+			Verification:      &verification.VerificationModule{},
+			A2HARBFileExist:   isA2HARBFileExist(),
+			ManagedServicesOn: isManagedServicesOn(),
+		}
+		return c.runVerifyCmd(cmd, args, flagsObj)
+	}
+}
+
+func (v *verifyCmdFlow) runVerifyCmd(cmd *cobra.Command, args []string, flagsObj *verifyCmdFlags) error {
+	var configPath = ""
+	if len(args) > 0 {
+		configPath = args[0]
+	}
+
+	switch true {
+	case flagsObj.haAWSProvision:
+		err := v.verifyHaAWSProvision(configPath)
+		return err
+	case flagsObj.haAWSManagedProvision:
+		err := v.verifyHaAWSManagedProvision(configPath)
+		return err
+	case flagsObj.haAWSDeploy:
+		err := v.verifyHaAWSDeploy(configPath)
+		return err
+	case flagsObj.haAWSManagedDeploy:
+		err := v.verifyHaAWSManagedDeploy(configPath)
+		return err
+	case flagsObj.standaloneDeploy:
+		err := v.verifyStandaloneDeploy(configPath)
+		return err
+	case flagsObj.haOnpremDeploy:
+		err := v.verifyHaOnpremDeploy(configPath)
+		return err
+	case flagsObj.haOnPremAWSManagedDeploy:
+		err := v.verifyHaOnPremAWSManagedDeploy(configPath)
+		return err
+	case flagsObj.haOnPremCustManagedDeploy:
+		err := v.verifyHaOnPremCustManagedDeploy(configPath)
+		return err
+	case flagsObj.certificates:
+		err := v.Verification.VerifyCertificates("")
+		return err
+	default:
+		fmt.Println(cmd.UsageString())
+		return nil
+	}
+
+}
+
+func (v *verifyCmdFlow) verifyHaAWSProvision(configPath string) error {
+	if err := v.Verification.VerifyHAAWSProvision(configPath); err != nil {
+		return status.Annotate(err, status.ConfigError)
+	}
+
+	return nil
+}
+
+func (v *verifyCmdFlow) verifyHaAWSManagedProvision(configPath string) error {
+	if err := v.Verification.VerifyHAAWSManagedProvision(configPath); err != nil {
+		return status.Annotate(err, status.ConfigError)
+	}
+
+	return nil
+}
+
+func (v *verifyCmdFlow) verifyHaAWSDeploy(configPath string) error {
+	if !v.ManagedServicesOn {
+		if v.A2HARBFileExist {
+			if err := v.Verification.VerifyHAAWSDeployment(configPath); err != nil {
+				return status.Annotate(err, status.ConfigError)
+			}
+			return nil
+		}
+		return status.New(status.InvalidCommandArgsError, errProvisonInfra)
+	}
+	return status.New(status.InvalidCommandArgsError, "This flag will not verify the Managed Services Setup. Please use the --ha-aws-managed-deploy flag.")
+}
+
+func (v *verifyCmdFlow) verifyHaAWSManagedDeploy(configPath string) error {
+	if v.ManagedServicesOn {
+		if v.A2HARBFileExist {
+			if err := v.Verification.VerifyHAAWSManagedDeployment(configPath); err != nil {
+				return status.Annotate(err, status.ConfigError)
+			}
+			return nil
+		}
+		return status.New(status.InvalidCommandArgsError, errProvisonInfra)
+	}
+	return status.New(status.InvalidCommandArgsError, "Managed Services flag is not set. Cannot verify the config.")
+}
+
+func (v *verifyCmdFlow) verifyStandaloneDeploy(configPath string) error {
+	if v.A2HARBFileExist {
+		return status.New(status.InvalidCommandArgsError, "Deployment type does not match with the requested flag.")
+	}
+	if err := v.Verification.VerifyStandaloneDeployment(configPath); err != nil {
+		return status.Annotate(err, status.ConfigError)
+	}
+
+	return nil
+}
+
+func (v *verifyCmdFlow) verifyHaOnpremDeploy(configPath string) error {
+	if err := v.Verification.VerifyOnPremDeployment(configPath); err != nil {
+		return status.Annotate(err, status.ConfigError)
+	}
+	return nil
+}
+
+func (v *verifyCmdFlow) verifyHaOnPremAWSManagedDeploy(configPath string) error {
+	if err := v.Verification.VerifyOnPremAWSManagedDeployment(configPath); err != nil {
+		return status.Annotate(err, status.ConfigError)
+	}
+	return nil
+}
+
+func (v *verifyCmdFlow) verifyHaOnPremCustManagedDeploy(configPath string) error {
+	if err := v.Verification.VerifyOnPremCustManagedDeployment(configPath); err != nil {
+		return status.Annotate(err, status.ConfigError)
+	}
+	return nil
+}
diff --git a/go.mod b/go.mod
index c553dcab3..706b701d0 100644
--- a/go.mod
+++ b/go.mod
@@ -67,6 +67,7 @@ require (
 	github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 // indirect
 	github.com/imdario/mergo v0.3.13
 	github.com/jaswdr/faker v1.0.2
+	github.com/jedib0t/go-pretty/v5 v5.0.2-alpha
 	github.com/jhump/protoreflect v1.7.1-0.20200723220026-11eaaf73e0ec
 	github.com/kevinburke/go-bindata v3.16.0+incompatible
 	github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348
@@ -74,7 +75,6 @@ require (
 	github.com/lib/pq v1.8.0
 	github.com/lyft/protoc-gen-star v0.4.16-0.20200805193024-077ca8f98fb2
 	github.com/mattn/go-isatty v0.0.12 // indirect
-	github.com/mattn/go-runewidth v0.0.9 // indirect
 	github.com/mattn/go-sqlite3 v1.11.0 // indirect
 	github.com/minio/minio-go/v7 v7.0.14
 	github.com/mitchellh/go-homedir v1.1.0
diff --git a/go.sum b/go.sum
index aba2a3d83..a71edd28b 100644
--- a/go.sum
+++ b/go.sum
@@ -122,6 +122,8 @@ github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQh
 github.com/armon/go-metrics v0.3.2 h1:EyUnxyP2yaGpLgMiuyyz8sHnByqeTJUfGs72pdH0i4A=
 github.com/armon/go-metrics v0.3.2/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco=
+github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
 github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
@@ -236,6 +238,9 @@ github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2H
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.1-0.20180503022059-e9ed3c6dfb39 h1:8aiwjJixH9Dws9c0mE6yeghmrVhe6csuB+onSjeW31Q=
 github.com/ghodss/yaml v1.0.1-0.20180503022059-e9ed3c6dfb39/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
+github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is=
+github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/go-chef/chef v0.23.2-0.20201213054559-3243f736d651 h1:r1JMgPxoXlMKblknr8f6f3SafrfL2oKyPCqglTQN7xA=
 github.com/go-chef/chef v0.23.2-0.20201213054559-3243f736d651/go.mod h1:9Ptf9dFZDkpC3qLxpNhHMyG6TxCmMzonqPKXTh+xVm4=
 github.com/go-delve/delve v1.3.1 h1:LI0X4aAE0N7ay8uR48aMJ6GNTxamIpcxi1THjwJjenI=
@@ -253,6 +258,11 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
 github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
+github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
+github.com/go-openapi/errors v0.19.0 h1:guf3T2lnCBKlODmERt4T9GtMWRpJOikgKGyIvi0xcb8=
+github.com/go-openapi/errors v0.19.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
+github.com/go-openapi/strfmt v0.19.0 h1:0Dn9qy1G9+UJfRU7TR8bmdGxb4uifB7HNrJjOnV0yPk=
+github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
 github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
@@ -444,6 +454,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/jaswdr/faker v1.0.2 h1:3iRZztCC4oU67i67qGcyhIxeKgHQQH/iCifJOj3uOSI=
 github.com/jaswdr/faker v1.0.2/go.mod h1:9S4x1SRPC3m+iLgZTx2HZ0/R1/B0hwuL8uvOAiuJNtg=
+github.com/jedib0t/go-pretty/v5 v5.0.2-alpha h1:rRYHSFWZ3egaMVREb5NgN17UanLMWM2s7EhG3u/1Yy4=
+github.com/jedib0t/go-pretty/v5 v5.0.2-alpha/go.mod h1:DAKhNY3KVw+n6uMJ+WIzEs2XHfuQpMu2taSsKOXbTBw=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/jhump/protoreflect v1.7.1-0.20200723220026-11eaaf73e0ec h1:LeWD9kGWul9js18sWzNP2SjMuO6smUEpXt8OmRs7qU0=
 github.com/jhump/protoreflect v1.7.1-0.20200723220026-11eaaf73e0ec/go.mod h1:D8nEtk+lKr8kMTMiLayswAtSSeHYDaRYk9r78Cy11mM=
@@ -513,6 +525,8 @@ github.com/lyft/protoc-gen-star v0.4.16-0.20200805193024-077ca8f98fb2 h1:P5EAf1f
 github.com/lyft/protoc-gen-star v0.4.16-0.20200805193024-077ca8f98fb2/go.mod h1:mE8fbna26u7aEA2QCVvvfBU/ZrPgocG1206xAFPcs94=
 github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
 github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@@ -628,6 +642,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/profile v0.0.0-20170413231811-06b906832ed0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
 github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug=
 github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
 github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
@@ -913,6 +928,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20171017063910-8dbc5d05d6ed/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
diff --git a/lib/config_parser/parser.go b/lib/config_parser/parser.go
new file mode 100644
index 000000000..e37dc0c80
--- /dev/null
+++ b/lib/config_parser/parser.go
@@ -0,0 +1,78 @@
+package config_parser
+
+import (
+	sc "github.com/chef/automate/api/config/deployment"
+	"github.com/chef/automate/components/automate-cli/pkg/status"
+	"github.com/chef/automate/lib/io/fileutils"
+	ptoml "github.com/pelletier/go-toml"
+)
+
+type ConfigParser interface {
+	ParseAWSAutomateConfig(configFile string) (*HAAwsConfigToml, error)
+	ParseOnPremConfig(configFile string) (*HAOnPremConfigToml, error)
+	ParseStandaloneConfig(configFile string) (*sc.AutomateConfig, error)
+}
+
+type ConfigParserImpl struct{}
+
+func (cp *ConfigParserImpl) ParseAWSAutomateConfig(configFile string) (*HAAwsConfigToml, error) {
+	return ParseAWSAutomateConfig(configFile)
+}
+
+func (cp *ConfigParserImpl) ParseOnPremConfig(configFile string) (*HAOnPremConfigToml, error) {
+	return ParseOnPremConfig(configFile)
+}
+
+func (cp *ConfigParserImpl) ParseStandaloneConfig(configFile string) (*sc.AutomateConfig, error) {
+	return ParseStandaloneConfig(configFile)
+}
+
+func ParseAWSAutomateConfig(configFile string) (*HAAwsConfigToml, error) {
+
+	/* This function will read the config toml file and will try to parse it in the structure.
+	   On successful parse, it will return the config structure. This is applicable for both
+	   AWS Provision and Deployment configuration both with Chef Managed and AWS Managed resources. */
+
+	fileUtils := &fileutils.FileSystemUtils{}
+	templateBytes, err := fileUtils.ReadFile(configFile)
+	if err != nil {
+		return nil, status.Wrap(err, status.FileAccessError, "error in reading config toml file")
+	}
+	config := HAAwsConfigToml{}
+	err = ptoml.Unmarshal(templateBytes, &config)
+	if err != nil {
+		return nil, status.Wrap(err, status.ConfigError, "error in unmarshalling config toml file")
+	}
+	return &config, nil
+}
+
+func ParseOnPremConfig(configFile string) (*HAOnPremConfigToml, error) {
+
+	/* This function will read the OnPrem config toml file and will try to parse it in the structure.
+	   On successful parse, it will return the config structure. This is applicable for Chef Managed,
+	   AWS Managed and Customer Managed resources*/
+
+	fileUtils := &fileutils.FileSystemUtils{}
+	templateBytes, err := fileUtils.ReadFile(configFile)
+	if err != nil {
+		return nil, status.Wrap(err, status.FileAccessError, "error in reading config toml file")
+	}
+	config := HAOnPremConfigToml{}
+	err = ptoml.Unmarshal(templateBytes, &config)
+	if err != nil {
+		return nil, status.Wrap(err, status.ConfigError, "error in unmarshalling config toml file")
+	}
+	return &config, nil
+}
+
+func ParseStandaloneConfig(configFile string) (*sc.AutomateConfig, error) {
+
+	/* This function will read the Standalone Automate config toml file and will try to parse it in the structure.
+	   On successful parse, it will return the config structure. */
+
+	config, err := sc.LoadUserOverrideConfigFile(configFile)
+	if err != nil {
+		return nil, err
+	}
+	return config, nil
+}
diff --git a/lib/config_parser/setupConfig.go b/lib/config_parser/setupConfig.go
new file mode 100644
index 000000000..167d14e0e
--- /dev/null
+++ b/lib/config_parser/setupConfig.go
@@ -0,0 +1,262 @@
+package config_parser
+
+type CertByIP struct {
+	IP         string `toml:"ip"`
+	PrivateKey string `toml:"private_key"`
+	PublicKey  string `toml:"public_key"`
+	NodesDn    string `toml:"nodes_dn,omitempty"`
+}
+
+type HAAwsConfigToml struct {
+	Architecture struct {
+		ConfigInitials struct {
+			SecretsKeyFile              string `toml:"secrets_key_file"`
+			SecretsStoreFile            string `toml:"secrets_store_file"`
+			Architecture                string `toml:"architecture"`
+			WorkspacePath               string `toml:"workspace_path"`
+			SSHUser                     string `toml:"ssh_user"`
+			SSHKeyFile                  string `toml:"ssh_key_file"`
+			SSHPort                     string `toml:"ssh_port"`
+			SudoPassword                string `toml:"sudo_password"`
+			LoggingMonitoringManagement string `toml:"logging_monitoring_management"`
+			NewElk                      string `toml:"new_elk"`
+			ExistingElkInstanceIP       string `toml:"existing_elk_instance_ip"`
+			ExistingElkPort             string `toml:"existing_elk_port"`
+			ExistingElkCert             string `toml:"existing_elk_cert"`
+			ExistingElkUsername         string `toml:"existing_elk_username"`
+			ExistingElkPassword         string `toml:"existing_elk_password"`
+			BackupMount                 string `toml:"backup_mount"`
+			BackupConfig                string `toml:"backup_config"`
+			S3BucketName                string `toml:"s3_bucketName"`
+			HabitatUIDGid               string `toml:"habitat_uid_gid"`
+		} `toml:"aws"`
+	} `toml:"architecture"`
+	Automate struct {
+		Config struct {
+			AdminPassword     string     `toml:"admin_password"`
+			Fqdn              string     `toml:"fqdn"`
+			AutomateSetupType string     `toml:"automate_setup_type"`
+			InstanceCount     string     `toml:"instance_count"`
+			TeamsPort         string     `toml:"teams_port"`
+			ConfigFile        string     `toml:"config_file"`
+			EnableCustomCerts bool       `toml:"enable_custom_certs"`
+			RootCA            string     `toml:"root_ca"`
+			PrivateKey        string     `toml:"private_key"`
+			PublicKey         string     `toml:"public_key"`
+			CertsByIP         []CertByIP `toml:"certs_by_ip"`
+		} `toml:"config"`
+	} `toml:"automate"`
+	ChefServer struct {
+		Config struct {
+			InstanceCount     string     `toml:"instance_count"`
+			EnableCustomCerts bool       `toml:"enable_custom_certs"`
+			PrivateKey        string     `toml:"private_key"`
+			PublicKey         string     `toml:"public_key"`
+			CertsByIP         []CertByIP `toml:"certs_by_ip"`
+		} `toml:"config"`
+	} `toml:"chef_server"`
+	Opensearch struct {
+		Config struct {
+			InstanceCount     string     `toml:"instance_count"`
+			EnableCustomCerts bool       `toml:"enable_custom_certs"`
+			RootCA            string     `toml:"root_ca"`
+			AdminCert         string     `toml:"admin_cert"`
+			AdminKey          string     `toml:"admin_key"`
+			PrivateKey        string     `toml:"private_key"`
+			PublicKey         string     `toml:"public_key"`
+			AdminDn           string     `toml:"admin_dn"`
+			NodesDn           string     `toml:"nodes_dn"`
+			CertsByIP         []CertByIP `toml:"certs_by_ip"`
+		} `toml:"config"`
+	} `toml:"opensearch"`
+	Postgresql struct {
+		Config struct {
+			InstanceCount     string     `toml:"instance_count"`
+			EnableCustomCerts bool       `toml:"enable_custom_certs"`
+			RootCA            string     `toml:"root_ca"`
+			PrivateKey        string     `toml:"private_key"`
+			PublicKey         string     `toml:"public_key"`
+			CertsByIP         []CertByIP `toml:"certs_by_ip"`
+		} `toml:"config"`
+	} `toml:"postgresql"`
+	Aws struct {
+		Config struct {
+			Profile                      string   `toml:"profile"`
+			Region                       string   `toml:"region"`
+			AwsVpcId                     string   `toml:"aws_vpc_id"`
+			AwsCidrBlockAddr             string   `toml:"aws_cidr_block_addr"`
+			PrivateCustomSubnets         []string `toml:"private_custom_subnets"`
+			PublicCustomSubnets          []string `toml:"public_custom_subnets"`
+			SSHKeyPairName               string   `toml:"ssh_key_pair_name"`
+			SetupManagedServices         bool     `toml:"setup_managed_services"`
+			OpensearchDomainName         string   `toml:"managed_opensearch_domain_name"`
+			OpensearchDomainUrl          string   `toml:"managed_opensearch_domain_url"`
+			OpensearchUsername           string   `toml:"managed_opensearch_username"`
+			OpensearchUserPassword       string   `toml:"managed_opensearch_user_password"`
+			OpensearchCertificate        string   `toml:"managed_opensearch_certificate"`
+			AwsOsSnapshotRoleArn         string   `toml:"aws_os_snapshot_role_arn"`
+			OsUserAccessKeyId            string   `toml:"os_snapshot_user_access_key_id"`
+			OsUserAccessKeySecret        string   `toml:"os_snapshot_user_access_key_secret"`
+			RDSInstanceUrl               string   `toml:"managed_rds_instance_url"`
+			RDSSuperUserName             string   `toml:"managed_rds_superuser_username"`
+			RDSSuperUserPassword         string   `toml:"managed_rds_superuser_password"`
+			RDSDBUserName                string   `toml:"managed_rds_dbuser_username"`
+			RDSDBUserPassword            string   `toml:"managed_rds_dbuser_password"`
+			RDSCertificate               string   `toml:"managed_rds_certificate"`
+			AmiFilterName                string   `toml:"ami_filter_name"`
+			AmiFilterVirtType            string   `toml:"ami_filter_virt_type"`
+			AmiFilterOwner               string   `toml:"ami_filter_owner"`
+			AmiID                        string   `toml:"ami_id"`
+			LBAccessLogs                 string   `toml:"lb_access_logs"`
+			DeleteOnTermination          bool     `toml:"delete_on_termination"`
+			AutomateServerInstanceType   string   `toml:"automate_server_instance_type"`
+			ChefServerInstanceType       string   `toml:"chef_server_instance_type"`
+			OpensearchServerInstanceType string   `toml:"opensearch_server_instance_type"`
+			PostgresqlServerInstanceType string   `toml:"postgresql_server_instance_type"`
+			AutomateLbCertificateArn     string   `toml:"automate_lb_certificate_arn"`
+			ChefServerLbCertificateArn   string   `toml:"chef_server_lb_certificate_arn"`
+			AutomateEbsVolumeIops        string   `toml:"automate_ebs_volume_iops"`
+			AutomateEbsVolumeSize        string   `toml:"automate_ebs_volume_size"`
+			AutomateEbsVolumeType        string   `toml:"automate_ebs_volume_type"`
+			ChefEbsVolumeIops            string   `toml:"chef_ebs_volume_iops"`
+			ChefEbsVolumeSize            string   `toml:"chef_ebs_volume_size"`
+			ChefEbsVolumeType            string   `toml:"chef_ebs_volume_type"`
+			OpensearchEbsVolumeIops      string   `toml:"opensearch_ebs_volume_iops"`
+			OpensearchEbsVolumeSize      string   `toml:"opensearch_ebs_volume_size"`
+			OpensearchEbsVolumeType      string   `toml:"opensearch_ebs_volume_type"`
+			PostgresqlEbsVolumeIops      string   `toml:"postgresql_ebs_volume_iops"`
+			PostgresqlEbsVolumeSize      string   `toml:"postgresql_ebs_volume_size"`
+			PostgresqlEbsVolumeType      string   `toml:"postgresql_ebs_volume_type"`
+			XContact                     string   `toml:"X-Contact"`
+			XDept                        string   `toml:"X-Dept"`
+			XProject                     string   `toml:"X-Project"`
+			XProduction                  string   `toml:"X-Production"`
+			XCustomer                    string   `toml:"X-Customer"`
+			AwsAutomateRoute53Prefix     string   `toml:"aws_automate_route53_prefix"`
+			AwsChefServerRoute53Prefix   string   `toml:"aws_chef_server_route53_prefix"`
+			AwsRoute53HostedZone         string   `toml:"aws_route53_hosted_zone"`
+			PostrgesqlDbIdentifier       string   `toml:"postgresql_db_identifier"`
+			ElasticsearchDomainName      string   `toml:"elasticsearch_domain_name"`
+			RDSInstanceType              string   `toml:"rds_postgresql_instance_type"`
+			RDSRestoreIdentifier         string   `toml:"rds_postgresql_restore_identifier"`
+			DatadogAPIKey                string   `toml:"datadog_api_key"`
+			UseExistingManagedInfra      bool     `toml:"use_existing_managed_infra"`
+		} `toml:"config"`
+	} `toml:"aws"`
+}
+
+type HAOnPremConfigToml struct {
+	Architecture struct {
+		ConfigInitials struct {
+			SecretsKeyFile              string `toml:"secrets_key_file,omitempty"`
+			SecretsStoreFile            string `toml:"secrets_store_file,omitempty"`
+			Architecture                string `toml:"architecture,omitempty"`
+			WorkspacePath               string `toml:"workspace_path,omitempty"`
+			SSHUser                     string `toml:"ssh_user,omitempty"`
+			SSHKeyFile                  string `toml:"ssh_key_file,omitempty"`
+			SSHPort                     string `toml:"ssh_port,omitempty"`
+			SudoPassword                string `toml:"sudo_password,omitempty"`
+			LoggingMonitoringManagement string `toml:"logging_monitoring_management,omitempty"`
+			NewElk                      string `toml:"new_elk,omitempty"`
+			ExistingElkInstanceIP       string `toml:"existing_elk_instance_ip,omitempty"`
+			ExistingElkPort             string `toml:"existing_elk_port,omitempty"`
+			ExistingElkCert             string `toml:"existing_elk_cert,omitempty"`
+			ExistingElkUsername         string `toml:"existing_elk_username,omitempty"`
+			ExistingElkPassword         string `toml:"existing_elk_password,omitempty"`
+			BackupMount                 string `toml:"backup_mount,omitempty"`
+			HabitatUIDGid               string `toml:"habitat_uid_gid,omitempty"`
+			BackupConfig                string `toml:"backup_config,omitempty"`
+		} `toml:"existing_infra"`
+	} `toml:"architecture"`
+	Automate struct {
+		Config struct {
+			AdminPassword     string     `toml:"admin_password"`
+			Fqdn              string     `toml:"fqdn"`
+			InstanceCount     string     `toml:"instance_count"`
+			TeamsPort         string     `toml:"teams_port,omitempty"`
+			ConfigFile        string     `toml:"config_file"`
+			EnableCustomCerts bool       `toml:"enable_custom_certs"`
+			RootCA            string     `toml:"root_ca"`
+			PrivateKey        string     `toml:"private_key"`
+			PublicKey         string     `toml:"public_key"`
+			CertsByIP         []CertByIP `toml:"certs_by_ip"`
+		} `toml:"config"`
+	} `toml:"automate"`
+	ChefServer struct {
+		Config struct {
+			InstanceCount     string     `toml:"instance_count"`
+			EnableCustomCerts bool       `toml:"enable_custom_certs"`
+			PrivateKey        string     `toml:"private_key"`
+			PublicKey         string     `toml:"public_key"`
+			CertsByIP         []CertByIP `toml:"certs_by_ip"`
+		} `toml:"config"`
+	} `toml:"chef_server"`
+	Opensearch struct {
+		Config struct {
+			InstanceCount     string     `toml:"instance_count"`
+			EnableCustomCerts bool       `toml:"enable_custom_certs"`
+			RootCA            string     `toml:"root_ca"`
+			AdminCert         string     `toml:"admin_cert"`
+			AdminKey          string     `toml:"admin_key"`
+			PrivateKey        string     `toml:"private_key"`
+			PublicKey         string     `toml:"public_key"`
+			AdminDn           string     `toml:"admin_dn"`
+			NodesDn           string     `toml:"nodes_dn"`
+			CertsByIP         []CertByIP `toml:"certs_by_ip"`
+		} `toml:"config"`
+	} `toml:"opensearch"`
+	Postgresql struct {
+		Config struct {
+			InstanceCount     string     `toml:"instance_count"`
+			EnableCustomCerts bool       `toml:"enable_custom_certs"`
+			RootCA            string     `toml:"root_ca"`
+			PrivateKey        string     `toml:"private_key"`
+			PublicKey         string     `toml:"public_key"`
+			CertsByIP         []CertByIP `toml:"certs_by_ip"`
+		} `toml:"config"`
+	} `toml:"postgresql"`
+	ExistingInfra struct {
+		Config struct {
+			AutomatePrivateIps   []string `toml:"automate_private_ips"`
+			ChefServerPrivateIps []string `toml:"chef_server_private_ips"`
+			OpensearchPrivateIps []string `toml:"opensearch_private_ips"`
+			PostgresqlPrivateIps []string `toml:"postgresql_private_ips"`
+		} `toml:"config"`
+	} `toml:"existing_infra"`
+	ExternalDB struct {
+		Database struct {
+			Type       string `toml:"type"`
+			PostgreSQL struct {
+				PostgreSQLInstanceURL       string `toml:"instance_url"`
+				PostgreSQLSuperUserName     string `toml:"superuser_username"`
+				PostgreSQLSuperUserPassword string `toml:"superuser_password"`
+				PostgreSQLDBUserName        string `toml:"dbuser_username"`
+				PostgreSQLDBUserPassword    string `toml:"dbuser_password"`
+				PostgreSQLCertificate       string `toml:"postgresql_certificate"`
+				PostgreSQLRootCert          string `toml:"postgresql_root_cert"`
+			} `toml:"postgre_sql"`
+			Opensearch struct {
+				OpensearchInstanceURL       string `toml:"opensearch_domain_url"`
+				OpensearchSuperUserName     string `toml:"opensearch_username"`
+				OpensearchSuperUserPassword string `toml:"opensearch_user_password"`
+				OpensearchCertificate       string `toml:"opensearch_certificate"`
+				OpensearchRootCert          string `toml:"opensearch_root_cert"`
+				OpensearchDomainName        string `toml:"opensearch_domain_name"`
+				AWS                         struct {
+					AwsOsSnapshotRoleArn  string `toml:"aws_os_snapshot_role_arn"`
+					OsUserAccessKeyId     string `toml:"os_snapshot_user_access_key_id"`
+					OsUserAccessKeySecret string `toml:"os_snapshot_user_access_key_secret"`
+				} `toml:"aws"`
+			} `toml:"open_search"`
+		} `toml:"database"`
+	} `toml:"external"`
+	ObjectStorage struct {
+		Config struct {
+			BucketName string `toml:"bucket_name"`
+			AccessKey  string `toml:"access_key"`
+			SecretKey  string `toml:"secret_key"`
+			Endpoint   string `toml:"endpoint"`
+			Region     string `toml:"region"`
+		} `toml:"config"`
+	} `toml:"object_storage"`
+}
diff --git a/lib/reporting/helperForVerification.go b/lib/reporting/helperForVerification.go
new file mode 100644
index 000000000..cef0e25c1
--- /dev/null
+++ b/lib/reporting/helperForVerification.go
@@ -0,0 +1,312 @@
+package reporting
+
+import (
+	"fmt"
+	"sort"
+	"strings"
+	"time"
+
+	"github.com/jedib0t/go-pretty/v5/table"
+)
+
+type VerificationReport struct {
+	TableKey     string
+	Report       Info
+	TotalReports int
+}
+
+type Info struct {
+	Hostip        string         `json:"hostip,omitempty"`
+	Parameter     string         `json:"parameter,omitempty"`
+	Status        string         `json:"status,omitempty"`
+	StatusMessage *StatusMessage `json:"statusMessage,omitempty"`
+	SummaryInfo   *SummaryInfo   `json:"summaryInfo,omitempty"`
+}
+
+type StatusMessage struct {
+	MainMessage string   `json:"mainMessage,omitempty"`
+	SubMessage  []string `json:"subMessage,omitempty"`
+}
+
+type SummaryInfo struct {
+	SuccessfulCount int      `json:"successfulCount,omitempty"`
+	FailedCount     int      `json:"failedCount,omitempty"`
+	ToResolve       []string `json:"toResolve,omitempty"`
+}
+
+type progress struct {
+	currentCount int
+	totalCount   int
+}
+
+func VerificationReports(reportChan chan VerificationReport, reporting Reporting, nodeInfoMap map[string][]Info, done chan bool) {
+	tableProgress := make(map[string]progress)
+	keyMap := make(map[string][]string)
+	tableKeys := reporting.GetAllTableKeys()
+	oldProgresslen := 0
+	for n := range reportChan {
+		time.Sleep(time.Second * 1)
+		report := n
+		info := report.Report
+		total := report.TotalReports
+		node := report.TableKey
+		var nodeinfo []Info
+		if _, ok := nodeInfoMap[node]; ok {
+			nodeinfo := nodeInfoMap[node]
+			nodeinfo = append(nodeinfo, info)
+			nodeInfoMap[node] = nodeinfo
+			oldCount := tableProgress[node].currentCount
+			tableProgress[node] = progress{
+				currentCount: oldCount + 1,
+				totalCount:   total,
+			}
+		} else {
+			nodeinfo = append(nodeinfo, info)
+			nodeInfoMap[node] = nodeinfo
+			keyMap[node] = matchNodeNameWithRespectiveTablesName(node, tableKeys)
+			tableProgress[node] = progress{
+				currentCount: 1,
+				totalCount:   total,
+			}
+		}
+		oldProgresslen = showProgress(tableProgress, oldProgresslen)
+	}
+	clearPrintedProgressMsg(len(tableProgress))
+	updateTablesWithData(reporting, nodeInfoMap, keyMap)
+	printTables(reporting, nodeInfoMap, keyMap)
+	done <- true
+}
+
+func printTables(reporting Reporting, nodeInfo map[string][]Info, keyMap map[string][]string) {
+	var summaryTables []*Table
+	keys := make([]string, len(nodeInfo))
+	i := 0
+	for key := range nodeInfo {
+		keys[i] = key
+		i++
+	}
+	sort.Strings(keys)
+	updateTableTitle(reporting, nodeInfo, keyMap)
+	for _, key := range keys {
+		statusTb := reporting.GetTable(keyMap[key][0])
+		summaryTb := reporting.GetTable(keyMap[key][1])
+		summaryTables = append(summaryTables, summaryTb)
+		printSingleTable(reporting, statusTb)
+	}
+	for _, summaryTable := range summaryTables {
+		printSingleTable(reporting, summaryTable)
+	}
+}
+
+func printSingleTable(reporting Reporting, table *Table) {
+	reporting.GenerateTableOutputAndPrint(table)
+	fmt.Print("\n")
+}
+
+func updateTablesWithData(reporting Reporting, nodeInfo map[string][]Info, keyMap map[string][]string) {
+	for key, value := range nodeInfo {
+		summaryMap := make(map[string]SummaryInfo)
+		statusTableRows, summaryTableRows := createSingleNodeRowsForBothTables(key, value, reporting, summaryMap)
+		reporting.GetTable(keyMap[key][0]).Rows = statusTableRows
+		reporting.GetTable(keyMap[key][1]).Rows = summaryTableRows
+	}
+}
+
+func createSingleNodeRowsForBothTables(title string, nodeInfo []Info, reporting Reporting, summaryMap map[string]SummaryInfo) ([]table.Row, []table.Row) {
+	var statusTableRows []table.Row
+	var summaryTableRows []table.Row
+	for idx, value := range nodeInfo {
+		singleRowEntry := createStatusTableRows(idx+1, &value, reporting)
+		statusTableRows = append(statusTableRows, singleRowEntry...)
+		summaryMap = createSummaryTableRowData(summaryMap, &value)
+	}
+	summaryTableRows = createSummaryTableRows(summaryMap, reporting)
+	return statusTableRows, summaryTableRows
+}
+
+func createStatusTableRows(index int, rowData *Info, reporting Reporting) []table.Row {
+	var row table.Row
+	var rows []table.Row
+
+	if rowData.Status == "Success" {
+		row = successRow(index, rowData, reporting)
+		rows = append(rows, row)
+	} else if rowData.Status == "Failed" {
+
+		row = failedRow(index, rowData, reporting)
+		rows = append(rows, row)
+	}
+	if len(rowData.StatusMessage.SubMessage) > 0 {
+		for _, value := range rowData.StatusMessage.SubMessage {
+			row = subMessageRow(value, rowData, reporting)
+			rows = append(rows, row)
+		}
+	}
+	return rows
+}
+
+func successRow(index int, rowData *Info, reporting Reporting) table.Row {
+	hostip := rowData.Hostip
+	parameter := rowData.Parameter
+	status := reporting.ChangeColour(Green, reporting.AppendSpecialCharater(Success, rowData.Status))
+	message := rowData.StatusMessage.MainMessage
+	row := table.Row{index, hostip, parameter, status, message}
+	return row
+}
+
+func failedRow(index int, rowData *Info, reporting Reporting) table.Row {
+	hostip := reporting.ChangeColour(Red, rowData.Hostip)
+	parameter := reporting.ChangeColour(Red, rowData.Parameter)
+	status := reporting.ChangeColour(Red, reporting.AppendSpecialCharater(Failed, rowData.Status))
+	message := reporting.ChangeColour(Red, rowData.StatusMessage.MainMessage)
+
+	row := table.Row{index, hostip, parameter, status, message}
+	return row
+}
+
+func subMessageRow(subMsg string, rowData *Info, reporting Reporting) table.Row {
+	var newSubMessage string
+	if rowData.Status == "Failed" {
+		key := reporting.AppendSpecialCharater(Failed, reporting.AppendSpecialCharater(SquareBracket, rowData.Status))
+		newSubMessage = reporting.ChangeColour(Red, key+subMsg)
+	} else {
+		key := reporting.ChangeColour(Yellow, reporting.AppendSpecialCharater(Warning, reporting.AppendSpecialCharater(SquareBracket, "Warning")))
+		newSubMessage = key + subMsg
+	}
+	row := table.Row{"", "", "", "", newSubMessage}
+	return row
+}
+
+func createSummaryTableRowData(summary map[string]SummaryInfo, rowData *Info) map[string]SummaryInfo {
+	var toResolve []string
+	if rowData.SummaryInfo.ToResolve != nil && len(rowData.SummaryInfo.ToResolve) > 0 {
+		toResolve = []string{fmt.Sprintf("%s:", rowData.Hostip)}
+		rowData.SummaryInfo.ToResolve = createIndexForToResolve(rowData.SummaryInfo.ToResolve)
+		toResolve = append(toResolve, rowData.SummaryInfo.ToResolve...)
+	}
+	if _, ok := summary[rowData.Parameter]; ok {
+		singleParameterSummary := summary[rowData.Parameter]
+		singleParameterSummary.SuccessfulCount = singleParameterSummary.SuccessfulCount + rowData.SummaryInfo.SuccessfulCount
+		singleParameterSummary.FailedCount = singleParameterSummary.FailedCount + rowData.SummaryInfo.FailedCount
+		singleParameterSummary.ToResolve = append(singleParameterSummary.ToResolve, toResolve...)
+
+		summary[rowData.Parameter] = singleParameterSummary
+		return summary
+	}
+
+	summary[rowData.Parameter] = SummaryInfo{
+		SuccessfulCount: rowData.SummaryInfo.SuccessfulCount,
+		FailedCount:     rowData.SummaryInfo.FailedCount,
+		ToResolve:       toResolve,
+	}
+
+	return summary
+}
+
+func createSummaryTableRows(rowData map[string]SummaryInfo, reporting Reporting) []table.Row {
+	var rows []table.Row
+	for key, value := range rowData {
+		if key != "" {
+			singleParameterRow := createSingleParameterRows(key, value, reporting)
+			rows = append(rows, singleParameterRow...)
+		}
+	}
+	return rows
+}
+
+func createSingleParameterRows(parameter string, parameterSummary SummaryInfo, reporting Reporting) []table.Row {
+	var row table.Row
+	var rows []table.Row
+	successCount := reporting.ChangeColour(Green, fmt.Sprintf("%d", parameterSummary.SuccessfulCount))
+	failedCount := reporting.ChangeColour(Red, fmt.Sprintf("%d", parameterSummary.FailedCount))
+	toResolve := parameterSummary.ToResolve
+	if len(toResolve) > 1 {
+		row = table.Row{parameter, successCount, failedCount, toResolve[0]}
+		rows = append(rows, row)
+		for _, value := range toResolve[1:] {
+			row = table.Row{"", "", "", value}
+			rows = append(rows, row)
+		}
+	} else {
+		row = table.Row{parameter, successCount, failedCount, ""}
+		rows = append(rows, row)
+	}
+	return rows
+}
+
+func showProgress(tableProgess map[string]progress, lines int) int {
+	clearPrintedProgressMsg(lines)
+	keys := make([]string, len(tableProgess))
+	i := 0
+	for key := range tableProgess {
+		keys[i] = key
+		i++
+	}
+	sort.Strings(keys)
+	for _, key := range keys {
+		percent := float64(tableProgess[key].currentCount) / float64(tableProgess[key].totalCount) * 100
+		progressMsg := fmt.Sprintf("%-12s %.2f%%\n", key, percent)
+		fmt.Print(progressMsg)
+	}
+	return len(keys)
+}
+
+func clearPrintedProgressMsg(lines int) {
+	if lines > 0 {
+		fmt.Printf("\033[%dA\033[J", lines)
+	}
+}
+
+func updateTableTitle(reporting Reporting, nodeInfo map[string][]Info, keyMap map[string][]string) {
+	var failed bool
+	for key, value := range nodeInfo {
+		title := reporting.GetTable(keyMap[key][0]).Title
+		if checkStatusNotEmpty(value) {
+			return
+		}
+		failed = checkFailedStatus(value)
+		if failed {
+			updatedTile := reporting.ChangeColour(Red, reporting.AppendSpecialCharater(Failed, title))
+			reporting.GetTable(keyMap[key][0]).Title = updatedTile
+		} else {
+			updatedTile := reporting.ChangeColour(Green, reporting.AppendSpecialCharater(Success, title))
+			reporting.GetTable(keyMap[key][0]).Title = updatedTile
+		}
+	}
+}
+
+func checkStatusNotEmpty(info []Info) bool {
+	for _, v := range info {
+		if v.Status == "" {
+			return true
+		}
+	}
+	return false
+}
+
+func checkFailedStatus(info []Info) bool {
+	for _, v := range info {
+		if v.Status == "Failed" {
+			return true
+		}
+	}
+	return false
+}
+
+func matchNodeNameWithRespectiveTablesName(substring string, keys []string) []string {
+	var matchingKeys []string
+	for _, key := range keys {
+		if strings.Contains(key, substring) {
+			matchingKeys = append(matchingKeys, key)
+		}
+	}
+	sort.Strings(matchingKeys)
+	return matchingKeys
+}
+
+func createIndexForToResolve(data []string) []string {
+	for key, value := range data {
+		data[key] = fmt.Sprintf("%d. %s", key+1, value)
+	}
+	return data
+}
diff --git a/lib/reporting/reporting.go b/lib/reporting/reporting.go
new file mode 100644
index 000000000..b054252a6
--- /dev/null
+++ b/lib/reporting/reporting.go
@@ -0,0 +1,130 @@
+package reporting
+
+import (
+	"sort"
+
+	"github.com/chef/automate/components/automate-deployment/pkg/cli"
+	"github.com/fatih/color"
+	"github.com/jedib0t/go-pretty/v5/table"
+)
+
+const (
+	Red = iota
+	Green
+	Yellow
+)
+
+const (
+	Failed = iota
+	Success
+	Warning
+	SquareBracket
+)
+
+type Reporting interface {
+	GetTable(key string) *Table
+	SetTable(key string, table *Table)
+	GetAllTableKeys() []string
+	GetAllTables() map[string]*Table
+	AppendSpecialCharater(symbol int, str string) string
+	ChangeColour(fgColor int, msg string) string
+	GenerateTableOutputAndPrint(table *Table)
+}
+
+type Table struct {
+	Title     string
+	Rows      []table.Row
+	Header    table.Row
+	Footer    table.Row
+	ColConfig []table.ColumnConfig
+}
+
+type ReportingModule struct {
+	writer *cli.Writer
+	tables map[string]*Table
+}
+
+func NewReportingModule(wr *cli.Writer, tables map[string]*Table) Reporting {
+	newReportingModule := &ReportingModule{
+		writer: wr,
+		tables: tables,
+	}
+	return newReportingModule
+}
+
+// GetTable returns table present in tables map for given key.
+func (r *ReportingModule) GetTable(key string) *Table {
+	return r.tables[key]
+}
+
+// GetAllTableKeys returns all keys present in tables map
+func (r *ReportingModule) GetAllTableKeys() []string {
+	keys := make([]string, len(r.tables))
+	i := 0
+	for key := range r.tables {
+		keys[i] = key
+		i++
+	}
+	sort.Strings(keys)
+	return keys
+}
+
+// GetAllTables returns tables map
+func (r *ReportingModule) GetAllTables() map[string]*Table {
+	return r.tables
+}
+
+// SetTable sets the value of tables[key] in tables map to table provided in argument
+func (r *ReportingModule) SetTable(key string, table *Table) {
+	r.tables[key] = table
+}
+
+// AppendSpecialCharater returns a string.
+// Function appends a special char at the start of the str provided in arguments and returns that string
+func (r *ReportingModule) AppendSpecialCharater(symbol int, str string) string {
+	failedSymbol := "✖ "
+	successSymbol := "✔ "
+	warningSymbol := "! "
+
+	switch symbol {
+	case Failed:
+		msg := failedSymbol + str
+		return msg
+	case Success:
+		msg := successSymbol + str
+		return msg
+	case Warning:
+		msg := warningSymbol + str
+		return msg
+	case SquareBracket:
+		msg := "[ " + str + " ] "
+		return msg
+	}
+
+	return str
+}
+
+// ChangeColour returns a string.
+// Function changes the color of the msg provided in arguments to the color given
+func (r *ReportingModule) ChangeColour(fgColor int, msg string) string {
+	switch fgColor {
+	case Red:
+		return color.New(color.FgRed).Sprint(msg)
+	case Green:
+		return color.New(color.FgGreen).Sprint(msg)
+	case Yellow:
+		return color.New(color.FgYellow).Sprint(msg)
+	default:
+		return msg
+	}
+}
+
+// GenerateTableOutputAndPrint prints table provided as argument
+func (r *ReportingModule) GenerateTableOutputAndPrint(tb *Table) {
+	tbWriter := table.NewWriter()
+	tbWriter.SetColumnConfigs(tb.ColConfig)
+	tbWriter.AppendHeader(tb.Header)
+	tbWriter.AppendRows(tb.Rows)
+	r.writer.Println(tb.Title)
+	r.writer.Println(tbWriter.Render())
+}
diff --git a/lib/verification/checks.go b/lib/verification/checks.go
new file mode 100644
index 000000000..849059ab9
--- /dev/null
+++ b/lib/verification/checks.go
@@ -0,0 +1,271 @@
+package verification
+
+import (
+	sc "github.com/chef/automate/api/config/deployment"
+	"github.com/chef/automate/lib/config_parser"
+	"github.com/chef/automate/lib/reporting"
+)
+
+const (
+	systemResources  = "System Resources"
+	softwareVersions = "Software Versions"
+)
+
+type Result struct {
+	Valid  bool
+	Report reporting.Info
+}
+
+func validateAWSProvisionConfig(config *config_parser.HAAwsConfigToml) {
+
+	/* Write the checks to validate if all the required fields for AWS Infra Provision without Managed Services
+	are filled in the parsed config */
+
+	if config.Aws.Config.SetupManagedServices {
+		/* Write the checks to validate if all the required fields for AWS Infra Provision with Managed Services
+		are filled in the parsed config */
+	}
+
+}
+
+func validateAWSManagedProvisionConfig(config *config_parser.HAAwsConfigToml) {
+
+	/* Write the checks to validate if all the required fields for AWS Infra Provision with Managed Services
+	are filled in the parsed config */
+
+}
+
+func validateAWSDeploymentConfig(config *config_parser.HAAwsConfigToml) {
+
+	/* Write the checks to validate if all the required fields for AWS Deployment without Managed Services
+	are filled in the parsed config */
+
+}
+
+func validateAWSManagedDeploymentConfig(config *config_parser.HAAwsConfigToml) {
+
+	/* Write the checks to validate if all the required fields for AWS Deployment with Managed Services
+	are filled in the parsed config */
+
+}
+
+func validateOnPremConfig(config *config_parser.HAOnPremConfigToml) {
+
+	/* Write the checks to validate if all the required fields for On-Prem Deployment with Chef Managed Services
+	are filled in the parsed config */
+
+}
+
+func validateOnPremAWSConfig(config *config_parser.HAOnPremConfigToml) {
+
+	/* Write the checks to validate if all the required fields for On-Prem Deployment with AWS Managed Services
+	are filled in the parsed config */
+
+}
+
+func validateOnPremCustomerConfig(config *config_parser.HAOnPremConfigToml) {
+
+	/* Write the checks to validate if all the required fields for On-Prem Deployment with Customer Managed Services
+	are filled in the parsed config */
+
+}
+
+func validateStandaloneDeploymentConfig(config *sc.AutomateConfig) {
+
+	/* Write the checks to validate if all the required fields for On-Prem Deployment with Customer Managed Services
+	are filled in the parsed config */
+
+}
+
+func validateNodeReachability(ipaddress string, nodeType string, channel chan reporting.VerificationReport, numberOfNodes *numberOfNodes) {
+
+	/* Write the checks to validate if the nodes are reachable */
+
+	result := reporting.Info{
+		Hostip:    ipaddress,
+		Parameter: "Node Reachabilility",
+		Status:    "Success",
+		StatusMessage: &reporting.StatusMessage{
+			MainMessage: "Node " + ipaddress + " is reachable",
+		},
+		SummaryInfo: &reporting.SummaryInfo{
+			SuccessfulCount: 1,
+		},
+	}
+
+	chanWriter(channel, nodeType, result, numberOfNodes)
+
+}
+
+func validateCertificateExpiry(ipaddress string, certContents string) Result {
+
+	return Result{
+		Valid: true,
+		Report: reporting.Info{
+			Hostip:    ipaddress,
+			Parameter: "Certificates",
+			Status:    "Success",
+			StatusMessage: &reporting.StatusMessage{
+				MainMessage: "Certificate A validated successfully",
+			},
+		},
+	}
+
+	/* Write the checks to validate the expiry date of the certificate */
+
+}
+
+func validateCertificateFormat(ipaddress string, certContents string) Result {
+
+	return Result{
+		Valid: true,
+		Report: reporting.Info{
+			Hostip:    ipaddress,
+			Parameter: "Certificates",
+			Status:    "Failed",
+			StatusMessage: &reporting.StatusMessage{
+				MainMessage: "Certificate B validation failed",
+				SubMessage:  []string{"Certificate is not formatted properly"},
+			},
+			SummaryInfo: &reporting.SummaryInfo{
+				ToResolve: []string{"Add the start and end certificate markers"},
+			},
+		},
+	}
+
+	/* Write the checks to validate the expiry date of the certificate */
+
+}
+
+func validateFreeDisk(ipaddress string, nodeType string) Result {
+
+	if nodeType == "OpenSearch" {
+		return Result{
+			Valid: false,
+			Report: reporting.Info{
+				Hostip:    ipaddress,
+				Parameter: systemResources,
+				Status:    "Failed",
+				StatusMessage: &reporting.StatusMessage{
+					MainMessage: "System Resources check failed",
+					SubMessage:  []string{"/hab volume is not of 100 GB"},
+				},
+				SummaryInfo: &reporting.SummaryInfo{
+					ToResolve: []string{"Re-mount the hab volume with 100 GB"},
+				},
+			},
+		}
+	}
+	return Result{
+		Valid: true,
+		Report: reporting.Info{
+			Hostip:    ipaddress,
+			Parameter: systemResources,
+			Status:    "Success",
+			StatusMessage: &reporting.StatusMessage{
+				MainMessage: "System Resources as per the requirement",
+			},
+		},
+	}
+
+}
+
+func validateCPU(ipaddress string, nodeType string) Result {
+
+	if nodeType == "ChefServer" {
+		return Result{
+			Valid: true,
+			Report: reporting.Info{
+				Hostip:    ipaddress,
+				Parameter: systemResources,
+				Status:    "Success",
+				StatusMessage: &reporting.StatusMessage{
+					MainMessage: "System Resources as per the requirement",
+				},
+			},
+		}
+	}
+	return Result{
+		Valid: false,
+		Report: reporting.Info{
+			Hostip:    ipaddress,
+			Parameter: systemResources,
+			Status:    "Failed",
+			StatusMessage: &reporting.StatusMessage{
+				MainMessage: "System Resources check failed",
+				SubMessage:  []string{"CPU count is not as per the requirement"},
+			},
+			SummaryInfo: &reporting.SummaryInfo{
+				ToResolve: []string{"Increase the CPU of the machine. Machine should have 4 CPUs"},
+			},
+		},
+	}
+
+}
+
+func validateOSVersion(ipaddress string, nodeType string) Result {
+
+	if nodeType == "Automate" {
+		return Result{
+			Valid: false,
+			Report: reporting.Info{
+				Hostip:    ipaddress,
+				Parameter: softwareVersions,
+				Status:    "Failed",
+				StatusMessage: &reporting.StatusMessage{
+					MainMessage: "Software Versions check Failed",
+					SubMessage:  []string{"OS version is not Ubuntu 20.04"},
+				},
+				SummaryInfo: &reporting.SummaryInfo{
+					ToResolve: []string{"Setup the machine with Ubuntu 20.04"},
+				},
+			},
+		}
+	}
+	return Result{
+		Valid: true,
+		Report: reporting.Info{
+			Hostip:    ipaddress,
+			Parameter: softwareVersions,
+			Status:    "Success",
+			StatusMessage: &reporting.StatusMessage{
+				MainMessage: "Software Versions check Passed",
+			},
+		},
+	}
+
+}
+
+func validateLinuxCommands(ipaddress string, nodeType string) Result {
+
+	if nodeType == "OpenSearch" {
+		return Result{
+			Valid: true,
+			Report: reporting.Info{
+				Hostip:    ipaddress,
+				Parameter: softwareVersions,
+				Status:    "Success",
+				StatusMessage: &reporting.StatusMessage{
+					MainMessage: "Software Versions check Failed",
+					SubMessage:  []string{"make command failed"},
+				},
+				SummaryInfo: &reporting.SummaryInfo{
+					ToResolve: []string{"Add the required paths in the PATH folder"},
+				},
+			},
+		}
+	}
+
+	return Result{
+		Valid: true,
+		Report: reporting.Info{
+			Hostip:    ipaddress,
+			Parameter: softwareVersions,
+			Status:    "Success",
+			StatusMessage: &reporting.StatusMessage{
+				MainMessage: "Software Versions check Passed",
+			},
+		},
+	}
+
+}
diff --git a/lib/verification/mockVerify.go b/lib/verification/mockVerify.go
new file mode 100644
index 000000000..b8318648b
--- /dev/null
+++ b/lib/verification/mockVerify.go
@@ -0,0 +1,49 @@
+package verification
+
+type VerificationMock struct {
+	VerifyHAAWSProvisionFunc              func(configFile string) error
+	VerifyHAAWSManagedProvisionFunc       func(configFile string) error
+	VerifyHAAWSDeploymentFunc             func(configFile string) error
+	VerifyHAAWSManagedDeploymentFunc      func(configFile string) error
+	VerifyOnPremDeploymentFunc            func(configFile string) error
+	VerifyOnPremAWSManagedDeploymentFunc  func(configFile string) error
+	VerifyOnPremCustManagedDeploymentFunc func(configFile string) error
+	VerifyStandaloneDeploymentFunc        func(configFile string) error
+	VerifyCertificatesFunc                func(configFile string) error
+}
+
+func (v *VerificationMock) VerifyHAAWSProvision(configFile string) error {
+	return v.VerifyHAAWSProvisionFunc(configFile)
+}
+
+func (v *VerificationMock) VerifyHAAWSManagedProvision(configFile string) error {
+	return v.VerifyHAAWSManagedProvisionFunc(configFile)
+}
+
+func (v *VerificationMock) VerifyHAAWSDeployment(configFile string) error {
+	return v.VerifyHAAWSDeploymentFunc(configFile)
+}
+
+func (v *VerificationMock) VerifyHAAWSManagedDeployment(configFile string) error {
+	return v.VerifyHAAWSManagedDeploymentFunc(configFile)
+}
+
+func (v *VerificationMock) VerifyOnPremDeployment(configFile string) error {
+	return v.VerifyOnPremDeploymentFunc(configFile)
+}
+
+func (v *VerificationMock) VerifyOnPremAWSManagedDeployment(configFile string) error {
+	return v.VerifyOnPremAWSManagedDeploymentFunc(configFile)
+}
+
+func (v *VerificationMock) VerifyOnPremCustManagedDeployment(configFile string) error {
+	return v.VerifyOnPremCustManagedDeploymentFunc(configFile)
+}
+
+func (v *VerificationMock) VerifyStandaloneDeployment(configFile string) error {
+	return v.VerifyStandaloneDeploymentFunc(configFile)
+}
+
+func (v *VerificationMock) VerifyCertificates(configFile string) error {
+	return v.VerifyCertificatesFunc(configFile)
+}
diff --git a/lib/verification/verify.go b/lib/verification/verify.go
new file mode 100644
index 000000000..2684228d0
--- /dev/null
+++ b/lib/verification/verify.go
@@ -0,0 +1,425 @@
+package verification
+
+import (
+	"fmt"
+	"os"
+	"sync"
+
+	"github.com/chef/automate/components/automate-deployment/pkg/cli"
+	"github.com/chef/automate/lib/config_parser"
+	"github.com/chef/automate/lib/reporting"
+	"github.com/jedib0t/go-pretty/v5/table"
+)
+
+type Verification interface {
+	VerifyHAAWSProvision(configFile string) error
+	VerifyHAAWSManagedProvision(configFile string) error
+	VerifyHAAWSDeployment(configFile string) error
+	VerifyHAAWSManagedDeployment(configFile string) error
+	VerifyOnPremDeployment(configFile string) error
+	VerifyOnPremAWSManagedDeployment(configFile string) error
+	VerifyOnPremCustManagedDeployment(configFile string) error
+	VerifyStandaloneDeployment(configFile string) error
+	VerifyCertificates(configFile string) error
+}
+
+type VerificationModule struct{}
+
+type report struct {
+	ipaddress             string
+	parameter             string
+	message               string
+	errors                []string
+	resolutions           []string
+	successfulChecksCount int
+	failedChecksCount     int
+}
+
+type numberOfNodes struct {
+	numberOfAutomateNodes    int
+	numberOfChefServerNodes  int
+	numberOfPostgresSQLNodes int
+	numberOfOpenSearchNodes  int
+}
+
+var reportChan = make(chan reporting.VerificationReport)
+var nodeInfoMap = make(map[string][]reporting.Info)
+var doneChan = make(chan bool, 1)
+
+func (v *VerificationModule) VerifyHAAWSProvision(configFile string) error {
+	configParser := &config_parser.ConfigParserImpl{}
+	config, err := configParser.ParseAWSAutomateConfig(configFile)
+	if err != nil {
+		return err
+	}
+
+	validateAWSProvisionConfig(config)
+	return nil
+}
+
+func (v *VerificationModule) VerifyHAAWSManagedProvision(configFile string) error {
+	configParser := &config_parser.ConfigParserImpl{}
+	config, err := configParser.ParseAWSAutomateConfig(configFile)
+	if err != nil {
+		return err
+	}
+	validateAWSManagedProvisionConfig(config)
+	return nil
+}
+
+func (v *VerificationModule) VerifyHAAWSDeployment(configFile string) error {
+	configParser := &config_parser.ConfigParserImpl{}
+	config, err := configParser.ParseAWSAutomateConfig(configFile)
+	if err != nil {
+		return err
+	}
+	validateAWSDeploymentConfig(config)
+	return nil
+}
+
+func (v *VerificationModule) VerifyHAAWSManagedDeployment(configFile string) error {
+	configParser := &config_parser.ConfigParserImpl{}
+	config, err := configParser.ParseAWSAutomateConfig(configFile)
+	if err != nil {
+		return err
+	}
+	validateAWSManagedDeploymentConfig(config)
+	return nil
+}
+
+func (v *VerificationModule) VerifyOnPremAWSManagedDeployment(configFile string) error {
+	configParser := &config_parser.ConfigParserImpl{}
+	config, err := configParser.ParseOnPremConfig(configFile)
+	if err != nil {
+		return err
+	}
+	validateOnPremAWSConfig(config)
+	return nil
+}
+
+func (v *VerificationModule) VerifyOnPremCustManagedDeployment(configFile string) error {
+	configParser := &config_parser.ConfigParserImpl{}
+	config, err := configParser.ParseOnPremConfig(configFile)
+	if err != nil {
+		return err
+	}
+	validateOnPremCustomerConfig(config)
+	return nil
+}
+
+func (v *VerificationModule) VerifyStandaloneDeployment(configFile string) error {
+	configParser := &config_parser.ConfigParserImpl{}
+	config, err := configParser.ParseStandaloneConfig(configFile)
+	if err != nil {
+		return err
+	}
+	validateStandaloneDeploymentConfig(config)
+	return nil
+}
+
+func (v *VerificationModule) VerifyCertificates(certContents string) error {
+
+	return nil
+}
+
+func (v *VerificationModule) VerifyOnPremDeployment(configFile string) error {
+
+	configParser := &config_parser.ConfigParserImpl{}
+	config, err := configParser.ParseOnPremConfig(configFile)
+	if err != nil {
+		return err
+	}
+	var ipsMap = make(map[string]string)
+	automateIps := config.ExistingInfra.Config.AutomatePrivateIps
+	chefServerIps := config.ExistingInfra.Config.ChefServerPrivateIps
+	opensearchIps := config.ExistingInfra.Config.OpensearchPrivateIps
+	postgresIps := config.ExistingInfra.Config.PostgresqlPrivateIps
+
+	dataMap := map[string][]string{
+		"Automate":    automateIps,
+		"ChefServer":  chefServerIps,
+		"OpenSearch":  opensearchIps,
+		"PostgresSQL": postgresIps,
+	}
+
+	for nodeType, nodeIps := range dataMap {
+		constructMap(nodeIps, nodeType, &ipsMap)
+	}
+
+	numberOfNodes := &numberOfNodes{
+		numberOfAutomateNodes:    len(automateIps),
+		numberOfChefServerNodes:  len(chefServerIps),
+		numberOfPostgresSQLNodes: len(postgresIps),
+		numberOfOpenSearchNodes:  len(opensearchIps),
+	}
+
+	startReportModule(numberOfNodes)
+
+	//validateOnPremConfig(config)
+
+	runTests(ipsMap, numberOfNodes)
+
+	return nil
+}
+
+func constructMap(nodeIps []string, nodeType string, m *map[string]string) {
+	for _, val := range nodeIps {
+		(*m)[val] = nodeType
+	}
+}
+
+func runTests(ipsMap map[string]string, numberOfNodes *numberOfNodes) {
+	var wg sync.WaitGroup
+
+	for k, v := range ipsMap {
+		wg.Add(3)
+		ip := fmt.Sprintf("%v", k)
+		nodeType := fmt.Sprintf("%v", v)
+		if nodeType == "OpenSearch" || nodeType == "PostgresSQL" {
+			wg.Add(1)
+			go func() {
+				defer wg.Done()
+				producerChan := make(chan bool, 1)
+				runChecksForCertificates(ip, nodeType, producerChan, numberOfNodes)
+			}()
+		}
+		go func() {
+			defer wg.Done()
+			validateNodeReachability(ip, nodeType, reportChan, numberOfNodes)
+		}()
+		go func() {
+			defer wg.Done()
+			runChecksForSystemResources(ip, nodeType, numberOfNodes)
+		}()
+		go func() {
+			defer wg.Done()
+			runChecksForSoftwareVersions(ip, nodeType, numberOfNodes)
+		}()
+	}
+	wg.Wait()
+	close(reportChan)
+	if <-doneChan {
+		fmt.Println("done!!")
+	}
+}
+
+func runChecksForCertificates(ipaddress string, nodeType string, doneChan chan bool, numberOfNodes *numberOfNodes) {
+	var successCount, failedCount int
+	result := validateCertificateFormat(ipaddress, "abc")
+	if !result.Valid {
+		failedCount++
+		result.Report.SummaryInfo.FailedCount = failedCount
+		chanWriter(reportChan, nodeType, result.Report, numberOfNodes)
+	} else {
+		result = validateCertificateExpiry(ipaddress, "abc")
+		if !result.Valid {
+			failedCount++
+			result.Report.SummaryInfo.FailedCount = failedCount
+			chanWriter(reportChan, nodeType, result.Report, numberOfNodes)
+		} else {
+			successCount++
+			report := report{
+				ipaddress:             ipaddress,
+				parameter:             "Certificates",
+				message:               "Certificate validation successful",
+				successfulChecksCount: successCount,
+			}
+			chanWriter(reportChan, nodeType, getReport(report, "Success"), numberOfNodes)
+		}
+	}
+	doneChan <- true
+}
+
+func runChecksForSystemResources(ipaddress string, nodeType string, numberOfNodes *numberOfNodes) {
+	var successCount, failedCount int
+	var errors []string
+	var resolutions []string
+	failed := false
+
+	result := validateFreeDisk(ipaddress, nodeType)
+	if !result.Valid {
+		errors = append(errors, result.Report.StatusMessage.SubMessage...)
+		resolutions = append(resolutions, result.Report.SummaryInfo.ToResolve...)
+		failed = true
+		failedCount++
+	} else if result.Valid && result.Report.StatusMessage.SubMessage != nil {
+		errors = append(errors, result.Report.StatusMessage.SubMessage...)
+		resolutions = append(resolutions, result.Report.SummaryInfo.ToResolve...)
+		successCount++
+	} else if result.Valid {
+		successCount++
+	}
+
+	result = validateCPU(ipaddress, nodeType)
+	if !result.Valid {
+		errors = append(errors, result.Report.StatusMessage.SubMessage...)
+		resolutions = append(resolutions, result.Report.SummaryInfo.ToResolve...)
+		failed = true
+		failedCount++
+	} else if result.Valid && result.Report.StatusMessage.SubMessage != nil {
+		errors = append(errors, result.Report.StatusMessage.SubMessage...)
+		resolutions = append(resolutions, result.Report.SummaryInfo.ToResolve...)
+		successCount++
+	} else if result.Valid {
+		successCount++
+	}
+
+	if failed {
+		report := report{
+			ipaddress:             ipaddress,
+			parameter:             "System Resources",
+			message:               "System Resource Check failed",
+			errors:                errors,
+			resolutions:           resolutions,
+			failedChecksCount:     failedCount,
+			successfulChecksCount: successCount,
+		}
+		chanWriter(reportChan, nodeType, getReport(report, "Failed"), numberOfNodes)
+
+	} else {
+		report := report{
+			ipaddress:             ipaddress,
+			parameter:             "System Resources",
+			message:               "All System Resources are as per the requirement",
+			errors:                errors,
+			resolutions:           resolutions,
+			failedChecksCount:     failedCount,
+			successfulChecksCount: successCount,
+		}
+		chanWriter(reportChan, nodeType, getReport(report, "Success"), numberOfNodes)
+	}
+}
+
+func runChecksForSoftwareVersions(ipaddress string, nodeType string, numberOfNodes *numberOfNodes) {
+	var successCount, failedCount int
+	var errors []string
+	var resolutions []string
+	failed := false
+
+	result := validateOSVersion(ipaddress, nodeType)
+	if !result.Valid {
+		errors = append(errors, result.Report.StatusMessage.SubMessage...)
+		resolutions = append(resolutions, result.Report.SummaryInfo.ToResolve...)
+		failed = true
+		failedCount++
+	} else if result.Valid && result.Report.StatusMessage.SubMessage != nil {
+		errors = append(errors, result.Report.StatusMessage.SubMessage...)
+		resolutions = append(resolutions, result.Report.SummaryInfo.ToResolve...)
+		successCount++
+	} else if result.Valid {
+		successCount++
+	}
+
+	result = validateLinuxCommands(ipaddress, nodeType)
+	if !result.Valid {
+		errors = append(errors, result.Report.StatusMessage.SubMessage...)
+		resolutions = append(resolutions, result.Report.SummaryInfo.ToResolve...)
+		failed = true
+		failedCount++
+	} else if result.Valid && result.Report.StatusMessage.SubMessage != nil {
+		errors = append(errors, result.Report.StatusMessage.SubMessage...)
+		resolutions = append(resolutions, result.Report.SummaryInfo.ToResolve...)
+		successCount++
+	} else if result.Valid {
+		successCount++
+	}
+
+	if failed {
+		report := report{
+			ipaddress:             ipaddress,
+			parameter:             result.Report.Parameter,
+			message:               result.Report.StatusMessage.MainMessage,
+			errors:                errors,
+			resolutions:           resolutions,
+			failedChecksCount:     failedCount,
+			successfulChecksCount: successCount,
+		}
+		chanWriter(reportChan, nodeType, getReport(report, "Failed"), numberOfNodes)
+
+	} else {
+		report := report{
+			ipaddress:             ipaddress,
+			parameter:             result.Report.Parameter,
+			message:               result.Report.StatusMessage.MainMessage,
+			errors:                errors,
+			resolutions:           resolutions,
+			failedChecksCount:     failedCount,
+			successfulChecksCount: successCount,
+		}
+		chanWriter(reportChan, nodeType, getReport(report, "Success"), numberOfNodes)
+	}
+}
+
+func getReport(testReport report, status string) reporting.Info {
+	return reporting.Info{
+		Hostip:    testReport.ipaddress,
+		Parameter: testReport.parameter,
+		Status:    status,
+		StatusMessage: &reporting.StatusMessage{
+			MainMessage: testReport.message,
+			SubMessage:  testReport.errors,
+		},
+		SummaryInfo: &reporting.SummaryInfo{
+			ToResolve:       testReport.resolutions,
+			SuccessfulCount: testReport.successfulChecksCount,
+			FailedCount:     testReport.failedChecksCount,
+		},
+	}
+}
+
+func startReportModule(nodeNumbers *numberOfNodes) {
+	wr := cli.NewWriter(os.Stdout, os.Stderr, os.Stdin)
+	tb := createTables(nodeNumbers)
+	rp := reporting.NewReportingModule(wr, tb)
+	go reporting.VerificationReports(reportChan, rp, nodeInfoMap, doneChan)
+}
+
+func createTables(nodeNumbers *numberOfNodes) map[string]*reporting.Table {
+	automateSummaryTableTitle := fmt.Sprintf("Summary: Automate <Nodes> - %d", nodeNumbers.numberOfAutomateNodes)
+	chefServerSummaryTableTitle := fmt.Sprintf("Summary: Chef Infra Server <Nodes> - %d", nodeNumbers.numberOfChefServerNodes)
+	postgresSQLSummaryTableTitle := fmt.Sprintf("Summary: PostgresSQL <Nodes> - %d", nodeNumbers.numberOfPostgresSQLNodes)
+	openSearchSummaryTableTitle := fmt.Sprintf("Summary: Opensearch <Nodes> - %d", nodeNumbers.numberOfOpenSearchNodes)
+	tb := make(map[string]*reporting.Table)
+	tb["AutomateStatusTable"] = getStatusTable("Automate")
+	tb["AutomateSummaryTable"] = getSummaryTable(automateSummaryTableTitle)
+	tb["ChefServerStatusTable"] = getStatusTable("Chef Infra Server")
+	tb["ChefServerSummaryTable"] = getSummaryTable(chefServerSummaryTableTitle)
+	tb["PostgresSQLStatusTable"] = getStatusTable("PostgresSQL")
+	tb["PostgresSQLSummaryTable"] = getSummaryTable(postgresSQLSummaryTableTitle)
+	tb["OpenSearchStatusTable"] = getStatusTable("OpenSearch")
+	tb["OpenSearchSummaryTable"] = getSummaryTable(openSearchSummaryTableTitle)
+	return tb
+}
+
+func getStatusTable(title string) *reporting.Table {
+	return &reporting.Table{
+		Title:     title,
+		Header:    table.Row{"No.", "Identifier", "Parameter", "Status", "Message"},
+		ColConfig: []table.ColumnConfig{{Number: 1, WidthMax: 5, WidthMin: 5}, {Number: 2, WidthMax: 15, WidthMin: 15}, {Number: 3, WidthMax: 25, WidthMin: 25}, {Number: 4, WidthMax: 15, WidthMin: 15}, {Number: 5, WidthMax: 60, WidthMin: 60}},
+	}
+}
+
+func getSummaryTable(title string) *reporting.Table {
+	return &reporting.Table{
+		Title:     title,
+		Header:    table.Row{"Parameter", "Successful", "Failed", "How to resolve it"},
+		ColConfig: []table.ColumnConfig{{Number: 1, WidthMax: 30, WidthMin: 30}, {Number: 2, WidthMax: 15, WidthMin: 15}, {Number: 3, WidthMax: 15, WidthMin: 15}, {Number: 4, WidthMax: 60, WidthMin: 60}},
+	}
+}
+
+func chanWriter(reportChan chan reporting.VerificationReport, nodeType string, report reporting.Info, nodeNumbers *numberOfNodes) {
+	total := 3 * nodeNumbers.numberOfAutomateNodes
+	if nodeType == "ChefServer" {
+		total = 3 * nodeNumbers.numberOfChefServerNodes
+	} else if nodeType == "OpenSearch" {
+		total = 4 * nodeNumbers.numberOfOpenSearchNodes
+	} else if nodeType == "PostgresSQL" {
+		total = 4 * nodeNumbers.numberOfPostgresSQLNodes
+	}
+	msg := reporting.VerificationReport{
+		TableKey:     nodeType,
+		Report:       report,
+		TotalReports: total,
+	}
+	reportChan <- msg
+}


Test patch:
diff --git a/components/automate-cli/cmd/chef-automate/verify_test.go b/components/automate-cli/cmd/chef-automate/verify_test.go
new file mode 100644
index 000000000..6cc2ee3f5
--- /dev/null
+++ b/components/automate-cli/cmd/chef-automate/verify_test.go
@@ -0,0 +1,908 @@
+package main
+
+import (
+	"testing"
+
+	verification "github.com/chef/automate/lib/verification"
+	"github.com/pkg/errors"
+	"github.com/spf13/cobra"
+	"github.com/stretchr/testify/assert"
+)
+
+const (
+	configFileName       = "config.toml"
+	parseConfigFileError = "Unable to parse config file"
+)
+
+func TestVerifyCmdFunc(t *testing.T) {
+	type args struct {
+		flagsObj *verifyCmdFlags
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "Test VerifyCmdFunc",
+			args: args{
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            false,
+					haAWSManagedProvision:     false,
+					haOnpremDeploy:            false,
+					haOnPremAWSManagedDeploy:  false,
+					haOnPremCustManagedDeploy: false,
+					haAWSDeploy:               false,
+					haAWSManagedDeploy:        false,
+					standaloneDeploy:          false,
+					certificates:              false,
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := verifyCmdFunc(tt.args.flagsObj)
+			err := got(&cobra.Command{}, []string{})
+			assert.Equal(t, nil, err)
+		})
+	}
+}
+
+func TestRunVerifyCmd(t *testing.T) {
+	type args struct {
+		cmd      *cobra.Command
+		args     []string
+		flagsObj *verifyCmdFlags
+	}
+	tests := []struct {
+		name              string
+		args              args
+		A2HARBFileExist   bool
+		ManagedServicesOn bool
+		mockFunc          verification.Verification
+		wantErr           bool
+		err               error
+	}{
+		{
+			name: "Test VerifyHaAWSProvision",
+			args: args{
+				cmd:  &cobra.Command{},
+				args: []string{},
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            true,
+					haAWSManagedProvision:     false,
+					haOnpremDeploy:            false,
+					haOnPremAWSManagedDeploy:  false,
+					haOnPremCustManagedDeploy: false,
+					haAWSDeploy:               false,
+					haAWSManagedDeploy:        false,
+					standaloneDeploy:          false,
+					certificates:              false,
+				},
+			},
+			A2HARBFileExist: true,
+			mockFunc: &verification.VerificationMock{
+				VerifyHAAWSProvisionFunc: func(configFile string) error {
+					return nil
+				},
+			},
+			ManagedServicesOn: false,
+			wantErr:           false,
+		},
+		{
+			name: "Test VerifyHaAWSManagedProvision",
+			args: args{
+				cmd:  &cobra.Command{},
+				args: []string{},
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            false,
+					haAWSManagedProvision:     true,
+					haOnpremDeploy:            false,
+					haOnPremAWSManagedDeploy:  false,
+					haOnPremCustManagedDeploy: false,
+					haAWSDeploy:               false,
+					haAWSManagedDeploy:        false,
+					standaloneDeploy:          false,
+					certificates:              false,
+				},
+			},
+			A2HARBFileExist: false,
+			mockFunc: &verification.VerificationMock{
+				VerifyHAAWSManagedProvisionFunc: func(configFile string) error {
+					return nil
+				},
+			},
+			ManagedServicesOn: false,
+			wantErr:           false,
+		},
+		{
+			name: "Test VerifyHaOnpremDeploy",
+			args: args{
+				cmd:  &cobra.Command{},
+				args: []string{},
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            false,
+					haAWSManagedProvision:     false,
+					haOnpremDeploy:            true,
+					haOnPremAWSManagedDeploy:  false,
+					haOnPremCustManagedDeploy: false,
+					haAWSDeploy:               false,
+					haAWSManagedDeploy:        false,
+					standaloneDeploy:          false,
+					certificates:              false,
+				},
+			},
+			A2HARBFileExist: false,
+			mockFunc: &verification.VerificationMock{
+				VerifyOnPremDeploymentFunc: func(configFile string) error {
+					return nil
+				},
+			},
+			ManagedServicesOn: false,
+			wantErr:           false,
+		},
+		{
+			name: "Test VerifyHaOnPremAWSManagedDeploy",
+			args: args{
+				cmd:  &cobra.Command{},
+				args: []string{},
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            false,
+					haAWSManagedProvision:     false,
+					haOnpremDeploy:            false,
+					haOnPremAWSManagedDeploy:  true,
+					haOnPremCustManagedDeploy: false,
+					haAWSDeploy:               false,
+					haAWSManagedDeploy:        false,
+					standaloneDeploy:          false,
+					certificates:              false,
+				},
+			},
+			A2HARBFileExist: false,
+			mockFunc: &verification.VerificationMock{
+				VerifyOnPremAWSManagedDeploymentFunc: func(configFile string) error {
+					return nil
+				},
+			},
+			ManagedServicesOn: false,
+			wantErr:           false,
+		},
+		{
+			name: "Test VerifyHaOnPremCustManagedDeploy",
+			args: args{
+				cmd:  &cobra.Command{},
+				args: []string{configFileName},
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            false,
+					haAWSManagedProvision:     false,
+					haOnpremDeploy:            false,
+					haOnPremAWSManagedDeploy:  false,
+					haOnPremCustManagedDeploy: true,
+					haAWSDeploy:               false,
+					haAWSManagedDeploy:        false,
+					standaloneDeploy:          false,
+					certificates:              false,
+				},
+			},
+			A2HARBFileExist: false,
+			mockFunc: &verification.VerificationMock{
+				VerifyOnPremCustManagedDeploymentFunc: func(configFile string) error {
+					return nil
+				},
+			},
+			ManagedServicesOn: false,
+			wantErr:           false,
+		},
+		{
+			name: "Test VerifyHaAWSDeploy",
+			args: args{
+				cmd:  &cobra.Command{},
+				args: []string{},
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            false,
+					haAWSManagedProvision:     false,
+					haOnpremDeploy:            false,
+					haOnPremAWSManagedDeploy:  false,
+					haOnPremCustManagedDeploy: false,
+					haAWSDeploy:               true,
+					haAWSManagedDeploy:        false,
+					standaloneDeploy:          false,
+					certificates:              false,
+				},
+			},
+			A2HARBFileExist: true,
+			mockFunc: &verification.VerificationMock{
+				VerifyHAAWSDeploymentFunc: func(configFile string) error {
+					return nil
+				},
+			},
+			ManagedServicesOn: false,
+			wantErr:           false,
+		},
+		{
+			name: "Test VerifyHaAWSManagedDeploy",
+			args: args{
+				cmd:  &cobra.Command{},
+				args: []string{},
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            false,
+					haAWSManagedProvision:     false,
+					haOnpremDeploy:            false,
+					haOnPremAWSManagedDeploy:  false,
+					haOnPremCustManagedDeploy: false,
+					haAWSDeploy:               false,
+					haAWSManagedDeploy:        true,
+					standaloneDeploy:          false,
+					certificates:              false,
+				},
+			},
+			A2HARBFileExist: true,
+			mockFunc: &verification.VerificationMock{
+				VerifyHAAWSManagedDeploymentFunc: func(configFile string) error {
+					return nil
+				},
+			},
+			ManagedServicesOn: true,
+			wantErr:           false,
+		},
+		{
+			name: "Test VerifyStandaloneDeploy",
+			args: args{
+				cmd:  &cobra.Command{},
+				args: []string{},
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            false,
+					haAWSManagedProvision:     false,
+					haOnpremDeploy:            false,
+					haOnPremAWSManagedDeploy:  false,
+					haOnPremCustManagedDeploy: false,
+					haAWSDeploy:               false,
+					haAWSManagedDeploy:        false,
+					standaloneDeploy:          true,
+					certificates:              false,
+				},
+			},
+			A2HARBFileExist: false,
+			mockFunc: &verification.VerificationMock{
+				VerifyStandaloneDeploymentFunc: func(configFile string) error {
+					return nil
+				},
+			},
+			ManagedServicesOn: false,
+			wantErr:           false,
+		},
+		{
+			name: "Test VerifyCertificates",
+			args: args{
+				cmd:  &cobra.Command{},
+				args: []string{},
+				flagsObj: &verifyCmdFlags{
+					file:                      "",
+					haAWSProvision:            false,
+					haAWSManagedProvision:     false,
+					haOnpremDeploy:            false,
+					haOnPremAWSManagedDeploy:  false,
+					haOnPremCustManagedDeploy: false,
+					haAWSDeploy:               false,
+					haAWSManagedDeploy:        false,
+					standaloneDeploy:          false,
+					certificates:              true,
+				},
+			},
+			A2HARBFileExist: false,
+			mockFunc: &verification.VerificationMock{
+				VerifyCertificatesFunc: func(configFile string) error {
+					return nil
+				},
+			},
+			ManagedServicesOn: false,
+			wantErr:           false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := verifyCmdFlow{
+				Verification:      tt.mockFunc,
+				A2HARBFileExist:   tt.A2HARBFileExist,
+				ManagedServicesOn: tt.ManagedServicesOn,
+			}
+
+			err := v.runVerifyCmd(tt.args.cmd, tt.args.args, tt.args.flagsObj)
+
+			if tt.wantErr {
+				assert.EqualError(t, err, tt.err.Error())
+			} else {
+				assert.Equal(t, nil, err)
+			}
+		})
+	}
+}
+
+func TestVerifyHaAWSProvision(t *testing.T) {
+	type fields struct {
+		Verification      verification.Verification
+		A2HARBFileExist   bool
+		ManagedServicesOn bool
+	}
+	type args struct {
+		configPath string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Test VerifyHaAWSProvision: verification failed",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSProvisionFunc: func(configFile string) error {
+						return errors.New(parseConfigFileError)
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(parseConfigFileError),
+		},
+		{
+			name: "Test VerifyHaAWSProvision: verification successful",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSProvisionFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &verifyCmdFlow{
+				Verification:      tt.fields.Verification,
+				A2HARBFileExist:   tt.fields.A2HARBFileExist,
+				ManagedServicesOn: tt.fields.ManagedServicesOn,
+			}
+			err := v.verifyHaAWSProvision(tt.args.configPath)
+
+			if tt.wantErr {
+				assert.EqualError(t, err, tt.err.Error())
+			} else {
+				assert.Equal(t, nil, err)
+			}
+		})
+	}
+}
+
+func TestVerifyHaAWSManagedProvision(t *testing.T) {
+	type fields struct {
+		Verification      verification.Verification
+		A2HARBFileExist   bool
+		ManagedServicesOn bool
+	}
+	type args struct {
+		configPath string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Test VerifyHaAWSManagedProvision: verification failed",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSManagedProvisionFunc: func(configFile string) error {
+						return errors.New(parseConfigFileError)
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(parseConfigFileError),
+		},
+		{
+			name: "Test VerifyHaAWSManagedProvision: verification successful",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSManagedProvisionFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &verifyCmdFlow{
+				Verification:      tt.fields.Verification,
+				A2HARBFileExist:   tt.fields.A2HARBFileExist,
+				ManagedServicesOn: tt.fields.ManagedServicesOn,
+			}
+			err := v.verifyHaAWSManagedProvision(tt.args.configPath)
+			if tt.wantErr {
+				assert.EqualError(t, err, tt.err.Error())
+			} else {
+				assert.Equal(t, nil, err)
+			}
+		})
+	}
+}
+
+func TestVerifyHaAWSDeploy(t *testing.T) {
+	type fields struct {
+		Verification      verification.Verification
+		A2HARBFileExist   bool
+		ManagedServicesOn bool
+	}
+	type args struct {
+		configPath string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Test VerifyHaAWSDeploy: verification successful",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   true,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: false,
+		},
+		{
+			name: "Test VerifyHaAWSDeploy: verification failed",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSDeploymentFunc: func(configFile string) error {
+						return errors.New(parseConfigFileError)
+					},
+				},
+				A2HARBFileExist:   true,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(parseConfigFileError),
+		},
+		{
+			name: "Test VerifyHaAWSDeploy: a2ha.rb file not present",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(errProvisonInfra),
+		},
+		{
+			name: "Test VerifyHaAWSDeploy: Managed services present",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: true,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New("This flag will not verify the Managed Services Setup. Please use the --ha-aws-managed-deploy flag."),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &verifyCmdFlow{
+				Verification:      tt.fields.Verification,
+				A2HARBFileExist:   tt.fields.A2HARBFileExist,
+				ManagedServicesOn: tt.fields.ManagedServicesOn,
+			}
+			err := v.verifyHaAWSDeploy(tt.args.configPath)
+			if tt.wantErr {
+				assert.EqualError(t, err, tt.err.Error())
+			} else {
+				assert.Equal(t, nil, err)
+			}
+		})
+	}
+}
+
+func TestVerifyHaAWSManagedDeploy(t *testing.T) {
+	type fields struct {
+		Verification      verification.Verification
+		A2HARBFileExist   bool
+		ManagedServicesOn bool
+	}
+	type args struct {
+		configPath string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Test VerifyHaAWSManagedDeploy: verification successful",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSManagedDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   true,
+				ManagedServicesOn: true,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: false,
+		},
+		{
+			name: "Test VerifyHaAWSManagedDeploy: verification failed",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSManagedDeploymentFunc: func(configFile string) error {
+						return errors.New(parseConfigFileError)
+					},
+				},
+				A2HARBFileExist:   true,
+				ManagedServicesOn: true,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(parseConfigFileError),
+		},
+		{
+			name: "Test VerifyHaAWSManagedDeploy: a2ha.rb file not present",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSManagedDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: true,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(errProvisonInfra),
+		},
+		{
+			name: "Test VerifyHaAWSManagedDeploy: Managed services not present",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyHAAWSManagedDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New("Managed Services flag is not set. Cannot verify the config."),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &verifyCmdFlow{
+				Verification:      tt.fields.Verification,
+				A2HARBFileExist:   tt.fields.A2HARBFileExist,
+				ManagedServicesOn: tt.fields.ManagedServicesOn,
+			}
+			err := v.verifyHaAWSManagedDeploy(tt.args.configPath)
+			if tt.wantErr {
+				assert.EqualError(t, err, tt.err.Error())
+			} else {
+				assert.Equal(t, nil, err)
+			}
+		})
+	}
+}
+
+func TestVerifyStandaloneDeploy(t *testing.T) {
+	type fields struct {
+		Verification      verification.Verification
+		A2HARBFileExist   bool
+		ManagedServicesOn bool
+	}
+	type args struct {
+		configPath string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Test VerifyStandaloneDeploy: check a2ha.rb file",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyStandaloneDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   true,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New("Deployment type does not match with the requested flag."),
+		},
+		{
+			name: "Test VerifyStandaloneDeploy: verification failed",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyStandaloneDeploymentFunc: func(configFile string) error {
+						return errors.New(parseConfigFileError)
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(parseConfigFileError),
+		},
+		{
+			name: "Test VerifyStandaloneDeploy: verification successful",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyStandaloneDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &verifyCmdFlow{
+				Verification:      tt.fields.Verification,
+				A2HARBFileExist:   tt.fields.A2HARBFileExist,
+				ManagedServicesOn: tt.fields.ManagedServicesOn,
+			}
+			err := v.verifyStandaloneDeploy(tt.args.configPath)
+			if tt.wantErr {
+				assert.EqualError(t, err, tt.err.Error())
+			} else {
+				assert.Equal(t, nil, err)
+			}
+		})
+	}
+}
+
+func TestVerifyHaOnpremDeploy(t *testing.T) {
+	type fields struct {
+		Verification      verification.Verification
+		A2HARBFileExist   bool
+		ManagedServicesOn bool
+	}
+	type args struct {
+		configPath string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Test VerifyHaOnpremDeploy: verification successful",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyOnPremDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: false,
+		},
+		{
+			name: "Test VerifyHaOnpremDeploy: verification failed",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyOnPremDeploymentFunc: func(configFile string) error {
+						return errors.New(parseConfigFileError)
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(parseConfigFileError),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &verifyCmdFlow{
+				Verification:      tt.fields.Verification,
+				A2HARBFileExist:   tt.fields.A2HARBFileExist,
+				ManagedServicesOn: tt.fields.ManagedServicesOn,
+			}
+			err := v.verifyHaOnpremDeploy(tt.args.configPath)
+			if tt.wantErr {
+				assert.EqualError(t, err, tt.err.Error())
+			} else {
+				assert.Equal(t, nil, err)
+			}
+		})
+	}
+}
+
+func TestVerifyHaOnPremAWSManagedDeploy(t *testing.T) {
+	type fields struct {
+		Verification      verification.Verification
+		A2HARBFileExist   bool
+		ManagedServicesOn bool
+	}
+	type args struct {
+		configPath string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Test VerifyHaOnPremAWSManagedDeploy: verification successful",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyOnPremAWSManagedDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: false,
+		},
+		{
+			name: "Test VerifyHaOnPremAWSManagedDeploy: verification failed",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyOnPremAWSManagedDeploymentFunc: func(configFile string) error {
+						return errors.New(parseConfigFileError)
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(parseConfigFileError),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &verifyCmdFlow{
+				Verification:      tt.fields.Verification,
+				A2HARBFileExist:   tt.fields.A2HARBFileExist,
+				ManagedServicesOn: tt.fields.ManagedServicesOn,
+			}
+			err := v.verifyHaOnPremAWSManagedDeploy(tt.args.configPath)
+			if tt.wantErr {
+				assert.EqualError(t, err, tt.err.Error())
+			} else {
+				assert.Equal(t, nil, err)
+			}
+		})
+	}
+}
+
+func TestVerifyHaOnPremCustManagedDeploy(t *testing.T) {
+	type fields struct {
+		Verification      verification.Verification
+		A2HARBFileExist   bool
+		ManagedServicesOn bool
+	}
+	type args struct {
+		configPath string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Test VerifyHaOnPremCustManagedDeploy: verification successful",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyOnPremCustManagedDeploymentFunc: func(configFile string) error {
+						return nil
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: false,
+		},
+		{
+			name: "Test VerifyHaOnPremCustManagedDeploy: verification failed",
+			fields: fields{
+				Verification: &verification.VerificationMock{
+					VerifyOnPremCustManagedDeploymentFunc: func(configFile string) error {
+						return errors.New(parseConfigFileError)
+					},
+				},
+				A2HARBFileExist:   false,
+				ManagedServicesOn: false,
+			},
+			args:    args{configPath: configFileName},
+			wantErr: true,
+			err:     errors.New(parseConfigFileError),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &verifyCmdFlow{
+				Verification:      tt.fields.Verification,
+				A2HARBFileExist:   tt.fields.A2HARBFileExist,
+				ManagedServicesOn: tt.fields.ManagedServicesOn,
+			}
+			err := v.verifyHaOnPremCustManagedDeploy(tt.args.configPath)
+			if tt.wantErr {
+				assert.EqualError(t, err, tt.err.Error())
+			} else {
+				assert.Equal(t, nil, err)
+			}
+		})
+	}
+}
diff --git a/lib/config_parser/parser_test.go b/lib/config_parser/parser_test.go
new file mode 100644
index 000000000..8a78c3bf3
--- /dev/null
+++ b/lib/config_parser/parser_test.go
@@ -0,0 +1,250 @@
+package config_parser
+
+import (
+	"errors"
+	"reflect"
+	"testing"
+
+	sc "github.com/chef/automate/api/config/deployment"
+	w "github.com/chef/automate/api/config/shared/wrappers"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestParseAWSAutomateConfig(t *testing.T) {
+	type args struct {
+		configFile string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *HAAwsConfigToml
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Parse AWS Config successful",
+			args: args{configFile: "./testdata/AWSConfig.toml"},
+			want: &HAAwsConfigToml{Architecture: struct {
+				ConfigInitials struct {
+					SecretsKeyFile              string "toml:\"secrets_key_file\""
+					SecretsStoreFile            string "toml:\"secrets_store_file\""
+					Architecture                string "toml:\"architecture\""
+					WorkspacePath               string "toml:\"workspace_path\""
+					SSHUser                     string "toml:\"ssh_user\""
+					SSHKeyFile                  string "toml:\"ssh_key_file\""
+					SSHPort                     string "toml:\"ssh_port\""
+					SudoPassword                string "toml:\"sudo_password\""
+					LoggingMonitoringManagement string "toml:\"logging_monitoring_management\""
+					NewElk                      string "toml:\"new_elk\""
+					ExistingElkInstanceIP       string "toml:\"existing_elk_instance_ip\""
+					ExistingElkPort             string "toml:\"existing_elk_port\""
+					ExistingElkCert             string "toml:\"existing_elk_cert\""
+					ExistingElkUsername         string "toml:\"existing_elk_username\""
+					ExistingElkPassword         string "toml:\"existing_elk_password\""
+					BackupMount                 string "toml:\"backup_mount\""
+					BackupConfig                string "toml:\"backup_config\""
+					S3BucketName                string "toml:\"s3_bucketName\""
+					HabitatUIDGid               string "toml:\"habitat_uid_gid\""
+				} "toml:\"aws\""
+			}{
+				ConfigInitials: struct {
+					SecretsKeyFile              string "toml:\"secrets_key_file\""
+					SecretsStoreFile            string "toml:\"secrets_store_file\""
+					Architecture                string "toml:\"architecture\""
+					WorkspacePath               string "toml:\"workspace_path\""
+					SSHUser                     string "toml:\"ssh_user\""
+					SSHKeyFile                  string "toml:\"ssh_key_file\""
+					SSHPort                     string "toml:\"ssh_port\""
+					SudoPassword                string "toml:\"sudo_password\""
+					LoggingMonitoringManagement string "toml:\"logging_monitoring_management\""
+					NewElk                      string "toml:\"new_elk\""
+					ExistingElkInstanceIP       string "toml:\"existing_elk_instance_ip\""
+					ExistingElkPort             string "toml:\"existing_elk_port\""
+					ExistingElkCert             string "toml:\"existing_elk_cert\""
+					ExistingElkUsername         string "toml:\"existing_elk_username\""
+					ExistingElkPassword         string "toml:\"existing_elk_password\""
+					BackupMount                 string "toml:\"backup_mount\""
+					BackupConfig                string "toml:\"backup_config\""
+					S3BucketName                string "toml:\"s3_bucketName\""
+					HabitatUIDGid               string "toml:\"habitat_uid_gid\""
+				}{
+					SecretsKeyFile:   "/hab/a2_deploy_workspace/secrets.key",
+					SecretsStoreFile: "/hab/a2_deploy_workspace/secrets.json",
+					Architecture:     "aws",
+					WorkspacePath:    "/hab/a2_deploy_workspace",
+					BackupMount:      "/mnt/automate_backups",
+				},
+			}},
+			wantErr: false,
+			err:     nil,
+		},
+		{
+			name:    "Parse AWs Config file not found",
+			args:    args{configFile: "AWSConfig.toml"},
+			want:    nil,
+			wantErr: true,
+			err:     errors.New("error in reading config toml file: open AWSConfig.toml: no such file or directory"),
+		},
+		{
+			name:    "Parse AWs Config failed",
+			args:    args{configFile: "./testdata/AWSConfigFailure.toml"},
+			want:    nil,
+			wantErr: true,
+			err:     errors.New("error in unmarshalling config toml file: (30, 21): unescaped control character U+000A"),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			cp := &ConfigParserImpl{}
+			got, err := cp.ParseAWSAutomateConfig(tt.args.configFile)
+			if tt.wantErr {
+				assert.Equal(t, tt.err.Error(), err.Error())
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ConfigParserImpl.ParseAWSAutomateConfig() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestParseOnPremConfig(t *testing.T) {
+	type args struct {
+		configFile string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *HAOnPremConfigToml
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Parse OnPrem Config successful",
+			args: args{configFile: "./testdata/OnPremConfig.toml"},
+			want: &HAOnPremConfigToml{Architecture: struct {
+				ConfigInitials struct {
+					SecretsKeyFile              string "toml:\"secrets_key_file,omitempty\""
+					SecretsStoreFile            string "toml:\"secrets_store_file,omitempty\""
+					Architecture                string "toml:\"architecture,omitempty\""
+					WorkspacePath               string "toml:\"workspace_path,omitempty\""
+					SSHUser                     string "toml:\"ssh_user,omitempty\""
+					SSHKeyFile                  string "toml:\"ssh_key_file,omitempty\""
+					SSHPort                     string "toml:\"ssh_port,omitempty\""
+					SudoPassword                string "toml:\"sudo_password,omitempty\""
+					LoggingMonitoringManagement string "toml:\"logging_monitoring_management,omitempty\""
+					NewElk                      string "toml:\"new_elk,omitempty\""
+					ExistingElkInstanceIP       string "toml:\"existing_elk_instance_ip,omitempty\""
+					ExistingElkPort             string "toml:\"existing_elk_port,omitempty\""
+					ExistingElkCert             string "toml:\"existing_elk_cert,omitempty\""
+					ExistingElkUsername         string "toml:\"existing_elk_username,omitempty\""
+					ExistingElkPassword         string "toml:\"existing_elk_password,omitempty\""
+					BackupMount                 string "toml:\"backup_mount,omitempty\""
+					HabitatUIDGid               string "toml:\"habitat_uid_gid,omitempty\""
+					BackupConfig                string "toml:\"backup_config,omitempty\""
+				} "toml:\"existing_infra\""
+			}{
+				ConfigInitials: struct {
+					SecretsKeyFile              string "toml:\"secrets_key_file,omitempty\""
+					SecretsStoreFile            string "toml:\"secrets_store_file,omitempty\""
+					Architecture                string "toml:\"architecture,omitempty\""
+					WorkspacePath               string "toml:\"workspace_path,omitempty\""
+					SSHUser                     string "toml:\"ssh_user,omitempty\""
+					SSHKeyFile                  string "toml:\"ssh_key_file,omitempty\""
+					SSHPort                     string "toml:\"ssh_port,omitempty\""
+					SudoPassword                string "toml:\"sudo_password,omitempty\""
+					LoggingMonitoringManagement string "toml:\"logging_monitoring_management,omitempty\""
+					NewElk                      string "toml:\"new_elk,omitempty\""
+					ExistingElkInstanceIP       string "toml:\"existing_elk_instance_ip,omitempty\""
+					ExistingElkPort             string "toml:\"existing_elk_port,omitempty\""
+					ExistingElkCert             string "toml:\"existing_elk_cert,omitempty\""
+					ExistingElkUsername         string "toml:\"existing_elk_username,omitempty\""
+					ExistingElkPassword         string "toml:\"existing_elk_password,omitempty\""
+					BackupMount                 string "toml:\"backup_mount,omitempty\""
+					HabitatUIDGid               string "toml:\"habitat_uid_gid,omitempty\""
+					BackupConfig                string "toml:\"backup_config,omitempty\""
+				}{
+					SecretsKeyFile:   "/hab/a2_deploy_workspace/secrets.key",
+					SecretsStoreFile: "/hab/a2_deploy_workspace/secrets.json",
+					Architecture:     "existing_nodes",
+					WorkspacePath:    "/hab/a2_deploy_workspace",
+					SSHPort:          "22",
+					BackupMount:      "/mnt/automate_backups",
+				},
+			}},
+			wantErr: false,
+			err:     nil,
+		},
+		{
+			name:    "Parse OnPrem Config file not found",
+			args:    args{configFile: "OnPremConfig.toml"},
+			want:    nil,
+			wantErr: true,
+			err:     errors.New("error in reading config toml file: open OnPremConfig.toml: no such file or directory"),
+		},
+		{
+			name:    "Parse OnPrem Config failed",
+			args:    args{configFile: "./testdata/OnPremConfigFailure.toml"},
+			want:    nil,
+			wantErr: true,
+			err:     errors.New("error in unmarshalling config toml file: (10, 21): unescaped control character U+000A"),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			cp := &ConfigParserImpl{}
+			got, err := cp.ParseOnPremConfig(tt.args.configFile)
+			if tt.wantErr {
+				assert.Equal(t, tt.err.Error(), err.Error())
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ConfigParserImpl.ParseOnPremConfig() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestParseStandaloneConfig(t *testing.T) {
+	Cfg := sc.NewAutomateConfig()
+	Cfg.Global.V1.Fqdn = w.String("Public_DNS_name")
+	type args struct {
+		configFile string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *sc.AutomateConfig
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "Parse Standalone Config successful",
+			args: args{
+				configFile: "./testdata/StandaloneConfig.toml",
+			},
+			want:    Cfg,
+			wantErr: false,
+		},
+		{
+			name: "Parse Standalone Config failed",
+			args: args{
+				configFile: "StandaloneConfig.toml",
+			},
+			want:    &sc.AutomateConfig{},
+			wantErr: true,
+			err:     errors.New("Failed to read config file located at StandaloneConfig.toml: open StandaloneConfig.toml: no such file or directory"),
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			cp := &ConfigParserImpl{}
+			got, err := cp.ParseStandaloneConfig(tt.args.configFile)
+			if tt.wantErr {
+				assert.Equal(t, tt.err.Error(), err.Error())
+			} else {
+				assert.Equal(t, tt.want.Global.V1.Fqdn.GetValue(), got.Global.V1.Fqdn.GetValue())
+			}
+
+		})
+	}
+}
diff --git a/lib/config_parser/testdata/AWSConfig.toml b/lib/config_parser/testdata/AWSConfig.toml
new file mode 100644
index 000000000..a644d7720
--- /dev/null
+++ b/lib/config_parser/testdata/AWSConfig.toml
@@ -0,0 +1,37 @@
+# This is a Chef Automate AWS HA mode configuration file. You can run
+# 'chef-automate deploy' with this config file and it should
+# successfully create a new Chef Automate HA instances with default settings.
+
+[architecture.aws]
+## === INPUT NEEDED ===
+# Eg.: ssh_user = "ubuntu"
+ssh_user = ""
+
+# custome ssh port no to connect instances, default will be 22
+# Eg.: ssh_port = "22"
+ssh_port = ""
+
+# Private SSH key file path, which has access to all the instances.
+# Eg.: ssh_key_file = "~/.ssh/A2HA.pem"
+ssh_key_file = ""
+
+# Eg.: backup_config = "efs" or "s3"
+backup_config = ""
+
+#    Note: 1. To create new bucket, make sure to give a unique name
+#          2. User can also add existing bucket 
+#
+# If s3 is selected for backup_config,
+#     uncomment and add the value for following 's3_bucketName' attribute
+
+# s3_bucketName = ""
+## === ===
+
+secrets_key_file = "/hab/a2_deploy_workspace/secrets.key"
+secrets_store_file = "/hab/a2_deploy_workspace/secrets.json"
+architecture = "aws"
+workspace_path = "/hab/a2_deploy_workspace"
+
+# DON'T MODIFY THE BELOW LINE (backup_mount)
+backup_mount = "/mnt/automate_backups"
+
diff --git a/lib/config_parser/testdata/AWSConfigFailure.toml b/lib/config_parser/testdata/AWSConfigFailure.toml
new file mode 100644
index 000000000..d619a0c3f
--- /dev/null
+++ b/lib/config_parser/testdata/AWSConfigFailure.toml
@@ -0,0 +1,37 @@
+# This is a Chef Automate AWS HA mode configuration file. You can run
+# 'chef-automate deploy' with this config file and it should
+# successfully create a new Chef Automate HA instances with default settings.
+
+[architecture.aws]
+## === INPUT NEEDED ===
+# Eg.: ssh_user = "ubuntu"
+ssh_user = ""
+
+# custome ssh port no to connect instances, default will be 22
+# Eg.: ssh_port = "22"
+ssh_port = ""
+
+# Private SSH key file path, which has access to all the instances.
+# Eg.: ssh_key_file = "~/.ssh/A2HA.pem"
+ssh_key_file = ""
+
+# Eg.: backup_config = "efs" or "s3"
+backup_config = ""
+
+#    Note: 1. To create new bucket, make sure to give a unique name
+#          2. User can also add existing bucket 
+#
+# If s3 is selected for backup_config,
+#     uncomment and add the value for following 's3_bucketName' attribute
+
+# s3_bucketName = ""
+## === ===
+
+secrets_key_file = "/hab/a2_deploy_workspace/secrets.key
+secrets_store_file = "/hab/a2_deploy_workspace/secrets.json"
+architecture = "aws"
+workspace_path = "/hab/a2_deploy_workspace"
+
+# DON'T MODIFY THE BELOW LINE (backup_mount)
+backup_mount = "/mnt/automate_backups"
+
diff --git a/lib/config_parser/testdata/OnPremConfig.toml b/lib/config_parser/testdata/OnPremConfig.toml
new file mode 100644
index 000000000..c641c1a18
--- /dev/null
+++ b/lib/config_parser/testdata/OnPremConfig.toml
@@ -0,0 +1,15 @@
+# This is a Chef Automate on-prem HA mode configuration file. You can run
+# 'chef-automate deploy' with this config file, and it should
+# successfully create a new Chef Automate HA instance with default settings.
+[architecture.existing_infra]
+ssh_user = ""
+# private ssh key file path to access instances
+# Eg.: ssh_user = "~/.ssh/A2HA.pem"
+ssh_key_file = ""
+ssh_port = "22"
+secrets_key_file = "/hab/a2_deploy_workspace/secrets.key"
+secrets_store_file = "/hab/a2_deploy_workspace/secrets.json"
+architecture = "existing_nodes"
+# DON'T MODIFY THE BELOW LINE (workspace_path)
+workspace_path = "/hab/a2_deploy_workspace"
+backup_mount = "/mnt/automate_backups"
diff --git a/lib/config_parser/testdata/OnPremConfigFailure.toml b/lib/config_parser/testdata/OnPremConfigFailure.toml
new file mode 100644
index 000000000..8d34f84b8
--- /dev/null
+++ b/lib/config_parser/testdata/OnPremConfigFailure.toml
@@ -0,0 +1,15 @@
+# This is a Chef Automate on-prem HA mode configuration file. You can run
+# 'chef-automate deploy' with this config file, and it should
+# successfully create a new Chef Automate HA instance with default settings.
+[architecture.existing_infra]
+ssh_user = ""
+# private ssh key file path to access instances
+# Eg.: ssh_user = "~/.ssh/A2HA.pem"
+ssh_key_file = ""
+ssh_port = "22"
+secrets_key_file = "/hab/a2_deploy_workspace/secrets.key
+secrets_store_file = "/hab/a2_deploy_workspace/secrets.json"
+architecture = "existing_nodes"
+# DON'T MODIFY THE BELOW LINE (workspace_path)
+workspace_path = "/hab/a2_deploy_workspace"
+backup_mount = "/mnt/automate_backups"
diff --git a/lib/config_parser/testdata/StandaloneConfig.toml b/lib/config_parser/testdata/StandaloneConfig.toml
new file mode 100644
index 000000000..4097767d3
--- /dev/null
+++ b/lib/config_parser/testdata/StandaloneConfig.toml
@@ -0,0 +1,6 @@
+# This is a default Chef Automate configuration file. You can run
+# 'chef-automate deploy' with this config file and it should
+# successfully create a new Chef Automate instance with default settings.
+
+[global.v1]
+fqdn = "Public_DNS_name"
diff --git a/lib/reporting/helperForVerification_test.go b/lib/reporting/helperForVerification_test.go
new file mode 100644
index 000000000..a03e4597a
--- /dev/null
+++ b/lib/reporting/helperForVerification_test.go
@@ -0,0 +1,410 @@
+package reporting
+
+import (
+	"testing"
+
+	"github.com/chef/automate/components/automate-deployment/pkg/cli"
+	"github.com/fatih/color"
+	"github.com/jedib0t/go-pretty/v5/table"
+	"github.com/stretchr/testify/assert"
+)
+
+const (
+	automate     = "Automate"
+	certificate  = "Certificates"
+	toResolveMsg = "1. Add the start and end certificate markers"
+	summaryTable = "AutomateSummaryTable"
+	ip           = "127.0.0.4"
+	ipResult     = "127.0.0.4:"
+)
+
+var tbMap = map[string]*Table{
+	automate: {
+		Title:     automate,
+		Header:    table.Row{"No.", "Identifier", "Parameter", "Status", "Message"},
+		ColConfig: []table.ColumnConfig{{Number: 1, WidthMax: 5, WidthMin: 5}, {Number: 2, WidthMax: 15, WidthMin: 15}, {Number: 3, WidthMax: 25, WidthMin: 25}, {Number: 4, WidthMax: 15, WidthMin: 15}, {Number: 5, WidthMax: 60, WidthMin: 60}},
+	},
+	summaryTable: {
+		Title:     "SUMMARY : Automate",
+		Header:    table.Row{"Parameter", "Successful", "Failed", "How to resolve it"},
+		ColConfig: []table.ColumnConfig{{Number: 1, WidthMax: 30, WidthMin: 30}, {Number: 2, WidthMax: 15, WidthMin: 15}, {Number: 3, WidthMax: 15, WidthMin: 15}, {Number: 4, WidthMax: 65, WidthMin: 65}},
+	},
+}
+
+func getMockReportingModule(wr *cli.Writer) Reporting {
+	return &ReportingModule{
+		writer: wr,
+		tables: tbMap,
+	}
+}
+
+var reportChan = make(chan VerificationReport, 10)
+var nodeInfoMap = make(map[string][]Info)
+var done = make(chan bool, 1)
+
+func TestVerificationReports(t *testing.T) {
+	cw := getMockWriterImpl()
+	type args struct {
+		reportChan  chan VerificationReport
+		reporting   Reporting
+		nodeInfoMap map[string][]Info
+		done        chan bool
+	}
+	test := struct {
+		name string
+		args args
+		want string
+	}{
+
+		name: successStr,
+		args: args{
+			reportChan:  reportChan,
+			reporting:   getMockReportingModule(cw.CliWriter),
+			nodeInfoMap: nodeInfoMap,
+			done:        done,
+		},
+		want: "Automate\n+-------+-----------------+---------------------------+-----------------+--------------------------------------------------------------+\n|   NO. |      IDENTIFIER |                 PARAMETER |          STATUS |                                                      MESSAGE |\n+-------+-----------------+---------------------------+-----------------+--------------------------------------------------------------+\n+-------+-----------------+---------------------------+-----------------+--------------------------------------------------------------+\nSUMMARY : Automate\n+--------------------------------+-----------------+-----------------+-------------------------------------------------------------------+\n|                      PARAMETER |      SUCCESSFUL |          FAILED |                                                 HOW TO RESOLVE IT |\n+--------------------------------+-----------------+-----------------+-------------------------------------------------------------------+\n+--------------------------------+-----------------+-----------------+-------------------------------------------------------------------+\n",
+	}
+
+	report := VerificationReport{
+		TableKey: "",
+		Report: Info{
+			Hostip:        "",
+			Parameter:     "",
+			Status:        "",
+			StatusMessage: &StatusMessage{},
+			SummaryInfo:   &SummaryInfo{},
+		},
+		TotalReports: 0,
+	}
+
+	reportChan <- report
+	reportChan <- report
+	close(reportChan)
+
+	VerificationReports(test.args.reportChan, test.args.reporting, test.args.nodeInfoMap, test.args.done)
+	if <-done {
+		assert.Equal(t, test.want, cw.Output())
+
+	}
+}
+
+func TestCreateStatusTableRows(t *testing.T) {
+	type args struct {
+		index     int
+		rowData   *Info
+		reporting Reporting
+	}
+	tests := []struct {
+		name string
+		args args
+		want []table.Row
+	}{
+		{
+			name: "Status is Success",
+			args: args{
+				index: 1,
+				rowData: &Info{
+					Hostip:    ip,
+					Parameter: certificate,
+					Status:    successStr,
+					StatusMessage: &StatusMessage{
+						MainMessage: "Cerificate validation successful",
+						SubMessage:  []string{"Certificate about to expire <Date>"},
+					},
+					SummaryInfo: &SummaryInfo{},
+				},
+				reporting: getMockReportingModule(getMockWriterImpl().CliWriter),
+			},
+			want: []table.Row{{1, ip, certificate, color.New(color.FgGreen).Sprint("✔ Success"), "Cerificate validation successful"}, {"", "", "", "", color.New(color.FgYellow).Sprint("! [ Warning ] ") + "Certificate about to expire <Date>"}},
+		},
+		{
+			name: "Status is Failed",
+			args: args{
+				index: 1,
+				rowData: &Info{
+					Hostip:    ip,
+					Parameter: certificate,
+					Status:    failedStr,
+					StatusMessage: &StatusMessage{
+						MainMessage: "Certificate validation failed",
+						SubMessage:  []string{"Certificate is not formatted properly"},
+					},
+					SummaryInfo: &SummaryInfo{},
+				},
+				reporting: getMockReportingModule(getMockWriterImpl().CliWriter),
+			},
+			want: []table.Row{{1, color.New(color.FgRed).Sprint(ip), color.New(color.FgRed).Sprint(certificate), color.New(color.FgRed).Sprint("✖ Failed"), color.New(color.FgRed).Sprint("Certificate validation failed")}, {"", "", "", "", color.New(color.FgRed).Sprint("✖ [ Failed ] Certificate is not formatted properly")}},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := createStatusTableRows(tt.args.index, tt.args.rowData, tt.args.reporting)
+			assert.Equal(t, tt.want, got)
+		})
+	}
+}
+
+func TestCreateSummaryTableRowData(t *testing.T) {
+	type args struct {
+		summary map[string]SummaryInfo
+		rowData *Info
+	}
+	tests := []struct {
+		name string
+		args args
+		want map[string]SummaryInfo
+	}{
+		{
+			name: successStr,
+			args: args{
+				summary: map[string]SummaryInfo{},
+				rowData: &Info{
+					Hostip:    ip,
+					Parameter: certificate,
+					Status:    failedStr,
+					StatusMessage: &StatusMessage{
+						MainMessage: "Certificate B validation failed",
+						SubMessage:  []string{"Certificate is not formatted properly"},
+					},
+					SummaryInfo: &SummaryInfo{
+						FailedCount: 1,
+						ToResolve:   []string{"Add the start and end certificate markers"},
+					},
+				},
+			},
+			want: map[string]SummaryInfo{
+				certificate: {
+					SuccessfulCount: 0,
+					FailedCount:     1,
+					ToResolve:       []string{ipResult, toResolveMsg},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := createSummaryTableRowData(tt.args.summary, tt.args.rowData)
+			assert.Equal(t, tt.want, got)
+		})
+	}
+}
+
+func TestCreateSummaryTableRows(t *testing.T) {
+	type args struct {
+		rowData   map[string]SummaryInfo
+		reporting Reporting
+	}
+	tests := []struct {
+		name string
+		args args
+		want []table.Row
+	}{
+		{
+			name: "ToResolve steps are present",
+			args: args{
+				rowData: map[string]SummaryInfo{
+					certificate: {
+						SuccessfulCount: 0,
+						FailedCount:     1,
+						ToResolve:       []string{ipResult, toResolveMsg},
+					},
+				},
+				reporting: getMockReportingModule(getMockWriterImpl().CliWriter),
+			},
+			want: []table.Row{{"Certificates", color.New(color.FgGreen).Sprint("0"), color.New(color.FgRed).Sprint("1"), ipResult}, {"", "", "", toResolveMsg}},
+		},
+		{
+			name: "ToResolve steps are not present",
+			args: args{
+				rowData: map[string]SummaryInfo{
+					certificate: {
+						SuccessfulCount: 1,
+						FailedCount:     0,
+						ToResolve:       []string{},
+					},
+				},
+				reporting: getMockReportingModule(getMockWriterImpl().CliWriter),
+			},
+			want: []table.Row{{"Certificates", color.New(color.FgGreen).Sprint("1"), color.New(color.FgRed).Sprint("0"), ""}},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := createSummaryTableRows(tt.args.rowData, tt.args.reporting)
+			assert.Equal(t, tt.want, got)
+		})
+	}
+}
+
+func TestShowProgress(t *testing.T) {
+	type args struct {
+		tableProgess map[string]progress
+		lines        int
+	}
+	test := struct {
+		name string
+		args args
+		want int
+	}{
+		name: successStr,
+		args: args{
+			tableProgess: map[string]progress{
+				automate: {
+					currentCount: 2,
+					totalCount:   3,
+				},
+			},
+			lines: 1,
+		},
+		want: 1,
+	}
+
+	got := showProgress(test.args.tableProgess, test.args.lines)
+	assert.Equal(t, test.want, got)
+
+}
+
+func TestUpdateTableTitle(t *testing.T) {
+	type args struct {
+		reporting Reporting
+		nodeInfo  map[string][]Info
+		keyMap    map[string][]string
+	}
+	tests := []struct {
+		name string
+		args args
+		want string
+	}{
+		{
+			name: "Title updated correctly when status is failed",
+			args: args{
+				reporting: getMockReportingModule(getMockWriterImpl().CliWriter),
+				nodeInfo: map[string][]Info{
+					automate: {
+						{
+							Hostip:    ip,
+							Parameter: certificate,
+							Status:    failedStr,
+						},
+					},
+				},
+				keyMap: map[string][]string{
+					automate: {automate, summaryTable},
+				},
+			},
+			want: color.New(color.FgRed).Sprint("✖ Automate"),
+		},
+		{
+			name: "Title updated correctly when status is succes",
+			args: args{
+				reporting: getMockReportingModule(getMockWriterImpl().CliWriter),
+				nodeInfo: map[string][]Info{
+					automate: {
+						{
+							Hostip:    ip,
+							Parameter: certificate,
+							Status:    successStr,
+						},
+					},
+				},
+				keyMap: map[string][]string{
+					automate: {automate, summaryTable},
+				},
+			},
+			want: color.New(color.FgGreen).Sprint("✔ Automate"),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			oldTitle := tt.args.reporting.GetTable(tt.args.keyMap[automate][0]).Title
+			updateTableTitle(tt.args.reporting, tt.args.nodeInfo, tt.args.keyMap)
+			assert.Equal(t, tt.want, tt.args.reporting.GetTable(tt.args.keyMap[automate][0]).Title)
+			tt.args.reporting.GetTable(tt.args.keyMap[automate][0]).Title = oldTitle
+		})
+	}
+}
+
+func TestCheckFailedStatus(t *testing.T) {
+	type args struct {
+		info []Info
+	}
+	tests := []struct {
+		name string
+		args args
+		want bool
+	}{
+		{
+			name: "Info array contains report with failed status",
+			args: args{
+				info: []Info{
+					{Status: failedStr},
+					{Status: successStr},
+					{Status: successStr},
+				},
+			},
+			want: true,
+		},
+		{
+			name: "Info array does not contains report with failed status",
+			args: args{
+				info: []Info{
+					{Status: successStr},
+					{Status: successStr},
+					{Status: successStr},
+				},
+			},
+			want: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := checkFailedStatus(tt.args.info); got != tt.want {
+				t.Errorf("checkFailedStatus() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestMatchNodeNameWithRespectiveTablesName(t *testing.T) {
+	type args struct {
+		substring string
+		keys      []string
+	}
+	test := struct {
+		name string
+		args args
+		want []string
+	}{
+		name: "Keys containing substring in alphabetical order",
+		args: args{
+			substring: "ab",
+			keys:      []string{"abab", "abc", "bcd", "bcda"},
+		},
+		want: []string{"abab", "abc"},
+	}
+
+	got := matchNodeNameWithRespectiveTablesName(test.args.substring, test.args.keys)
+	assert.Equal(t, test.want, got)
+}
+
+func TestCreateIndexForToResolve(t *testing.T) {
+	type args struct {
+		data []string
+	}
+	test := struct {
+		name string
+		args args
+		want []string
+	}{
+		name: successStr,
+		args: args{
+			data: []string{"Step 1", "Step 2"},
+		},
+		want: []string{"1. Step 1", "2. Step 2"},
+	}
+
+	got := createIndexForToResolve(test.args.data)
+	assert.Equal(t, test.want, got)
+
+}
diff --git a/lib/reporting/reporting_test.go b/lib/reporting/reporting_test.go
new file mode 100644
index 000000000..8eb54ace0
--- /dev/null
+++ b/lib/reporting/reporting_test.go
@@ -0,0 +1,367 @@
+package reporting
+
+import (
+	"reflect"
+	"testing"
+
+	"github.com/chef/automate/components/automate-deployment/pkg/cli"
+	"github.com/chef/automate/lib/majorupgrade_utils"
+	"github.com/fatih/color"
+	"github.com/jedib0t/go-pretty/v5/table"
+	"github.com/stretchr/testify/assert"
+)
+
+const (
+	successStr = "Success"
+	failedStr  = "Failed"
+	waringStr  = "Warning"
+	test1      = "test1"
+	test2      = "test2"
+	header     = "header"
+	header1    = "header1"
+	header2    = "header2"
+	col        = "col"
+	col1       = "col1"
+	col2       = "col2"
+)
+
+type fields struct {
+	writer *cli.Writer
+	tables map[string]*Table
+}
+
+var tableMap = map[string]*Table{
+	test1: {
+		Title:     test1,
+		Rows:      []table.Row{{col}},
+		Header:    table.Row{header},
+		Footer:    table.Row{},
+		ColConfig: []table.ColumnConfig{},
+	},
+	test2: {
+		Title:     test2,
+		Rows:      []table.Row{{col1, col2}},
+		Header:    table.Row{header1, header2},
+		Footer:    table.Row{},
+		ColConfig: []table.ColumnConfig{},
+	},
+}
+
+var module = fields{
+	writer: getMockWriterImpl().CliWriter,
+	tables: tableMap,
+}
+
+func TestNewReportingModule(t *testing.T) {
+	tests := []struct {
+		name string
+		args fields
+		want Reporting
+	}{
+		{
+			name: successStr,
+			args: module,
+			want: nil,
+		},
+	}
+	for _, tt := range tests {
+		NewReportingModule(tt.args.writer, tt.args.tables)
+	}
+}
+
+func TestGetTable(t *testing.T) {
+	tests := []struct {
+		name   string
+		fields fields
+		args   string
+		want   *Table
+	}{
+		{
+			name:   successStr,
+			fields: module,
+			args:   test1,
+			want: &Table{
+				Title:     test1,
+				Rows:      []table.Row{{col}},
+				Header:    table.Row{header},
+				Footer:    table.Row{},
+				ColConfig: []table.ColumnConfig{},
+			},
+		},
+	}
+	for _, tt := range tests {
+		r := &ReportingModule{
+			writer: tt.fields.writer,
+			tables: tt.fields.tables,
+		}
+		got := r.GetTable(tt.args)
+		assert.Equal(t, tt.want, got)
+	}
+}
+
+func TestGetAllTables(t *testing.T) {
+	tests := []struct {
+		name   string
+		fields fields
+		want   map[string]*Table
+	}{
+		{
+			name:   successStr,
+			fields: module,
+			want: map[string]*Table{
+				test1: {
+					Title:     test1,
+					Rows:      []table.Row{{col}},
+					Header:    table.Row{header},
+					Footer:    table.Row{},
+					ColConfig: []table.ColumnConfig{},
+				},
+				test2: {
+					Title:     test2,
+					Rows:      []table.Row{{col1, col2}},
+					Header:    table.Row{header1, header2},
+					Footer:    table.Row{},
+					ColConfig: []table.ColumnConfig{},
+				}},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			r := &ReportingModule{
+				writer: tt.fields.writer,
+				tables: tt.fields.tables,
+			}
+			if got := r.GetAllTables(); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ReportingModule.GetAllTables() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGetAllTableKeys(t *testing.T) {
+	test := struct {
+		name   string
+		fields fields
+		want   []string
+	}{
+
+		name:   successStr,
+		fields: module,
+		want:   []string{test1, test2},
+	}
+
+	r := &ReportingModule{
+		writer: test.fields.writer,
+		tables: test.fields.tables,
+	}
+	got := r.GetAllTableKeys()
+	assert.Equal(t, test.want, got)
+
+}
+
+func TestSetTable(t *testing.T) {
+	testTableMap := map[string]*Table{
+		test1: {
+			Title:     test1,
+			Rows:      []table.Row{{col}},
+			Header:    table.Row{header},
+			Footer:    table.Row{},
+			ColConfig: []table.ColumnConfig{},
+		},
+		test2: {
+			Title:     test2,
+			Rows:      []table.Row{{col1, col2}},
+			Header:    table.Row{header1, header2},
+			Footer:    table.Row{},
+			ColConfig: []table.ColumnConfig{},
+		},
+	}
+	type args struct {
+		key   string
+		table *Table
+	}
+	test := struct {
+		name   string
+		fields fields
+		args   args
+		want   *Table
+	}{
+		name: "Replace old table with given table for given key",
+		fields: fields{
+			writer: getMockWriterImpl().CliWriter,
+			tables: testTableMap,
+		},
+		args: args{
+			key:   test1,
+			table: testTableMap[test2],
+		},
+		want: testTableMap[test2],
+	}
+
+	r := &ReportingModule{
+		writer: test.fields.writer,
+		tables: test.fields.tables,
+	}
+	r.SetTable(test.args.key, test.args.table)
+	assert.EqualValues(t, test.want, r.GetTable(test1))
+}
+
+func TestAppendSpecialCharater(t *testing.T) {
+	type args struct {
+		symbol int
+		str    string
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   string
+	}{
+		{
+			name:   "Append x",
+			fields: module,
+			args: args{
+				symbol: Failed,
+				str:    failedStr,
+			},
+			want: "✖ Failed",
+		},
+		{
+			name:   "Append ✔",
+			fields: module,
+			args: args{
+				symbol: Success,
+				str:    successStr,
+			},
+			want: "✔ Success",
+		},
+		{
+			name:   "Append !",
+			fields: module,
+			args: args{
+				symbol: Warning,
+				str:    waringStr,
+			},
+			want: "! Warning",
+		},
+		{
+			name:   "Add [] bracket around text",
+			fields: module,
+			args: args{
+				symbol: SquareBracket,
+				str:    waringStr,
+			},
+			want: "[ Warning ] ",
+		},
+		{
+			name:   "String returned as it is",
+			fields: module,
+			args: args{
+				symbol: 4,
+				str:    waringStr,
+			},
+			want: waringStr,
+		},
+	}
+	for _, tt := range tests {
+		r := &ReportingModule{
+			writer: tt.fields.writer,
+			tables: tt.fields.tables,
+		}
+		got := r.AppendSpecialCharater(tt.args.symbol, tt.args.str)
+		assert.Equal(t, tt.want, got)
+	}
+}
+
+func TestChangeColour(t *testing.T) {
+	type args struct {
+		fgColor int
+		msg     string
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   string
+	}{
+		{
+			name:   "Change color of string to red",
+			fields: module,
+			args: args{
+				fgColor: Red,
+				msg:     test1,
+			},
+			want: color.New(color.FgRed).Sprint(test1),
+		},
+		{
+			name:   "Change color of string to green",
+			fields: module,
+			args: args{
+				fgColor: Green,
+				msg:     test1,
+			},
+			want: color.New(color.FgGreen).Sprint(test1),
+		},
+		{
+			name:   "Change color of string to yellow",
+			fields: module,
+			args: args{
+				fgColor: Yellow,
+				msg:     test1,
+			},
+			want: color.New(color.FgYellow).Sprint(test1),
+		},
+		{
+			name:   "Returned string is same as input",
+			fields: module,
+			args: args{
+				fgColor: 4,
+				msg:     test1,
+			},
+			want: test1,
+		},
+	}
+	for _, tt := range tests {
+		r := &ReportingModule{
+			writer: tt.fields.writer,
+			tables: tt.fields.tables,
+		}
+		got := r.ChangeColour(tt.args.fgColor, tt.args.msg)
+		assert.Equal(t, tt.want, got)
+	}
+}
+
+func TestGenerateTableOutputAndPrint(t *testing.T) {
+	cw := getMockWriterImpl()
+	type args struct {
+		tb *Table
+	}
+
+	test := struct {
+		name   string
+		fields fields
+		args   args
+		want   string
+	}{
+		name: "Print  given table",
+		fields: fields{
+			writer: cw.CliWriter,
+			tables: tableMap,
+		},
+		args: args{
+			tb: tableMap[test1],
+		},
+		want: "test1\n+--------+\n| HEADER |\n+--------+\n| col    |\n+--------+\n",
+	}
+
+	r := &ReportingModule{
+		writer: test.fields.writer,
+		tables: test.fields.tables,
+	}
+	r.GenerateTableOutputAndPrint(test.args.tb)
+	assert.Equal(t, test.want, cw.Output())
+}
+
+func getMockWriterImpl() *majorupgrade_utils.CustomWriter {
+	return majorupgrade_utils.NewCustomWriter()
+}