Repository: chef/automate
Pull request #8057 (2023-07-11 15:38:03)

Logic for checking Role for Bastion
### :nut_and_bolt: Description: What code changed, and why?
- Added the logic to check the Bastion Role present or not is aws_profile is not given 
- Added the functionality such that as if aws credentials are not given it should automatically picks IAM Role attached to the instance 
<!-- /!\ Please ensure that you are NOT disclosing any customer information without their consent /!\ -->

### :chains: Related Resources
- https://chefio.atlassian.net/browse/CHEF-3207
### :+1: Definition of Done

### :athletic_shoe: How to Build and Test the Change
- Rebuild components/autoamte-cli, automate-cluster-ctl, automate-ha-deployment, install that on  bastion
- Add the IAM Role for on your Bastion
- Start the Provision and Deployment for AWS Deployment
### :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
- AWS with Chef managed DB (Provision)
https://progresssoftware.sharepoint.com/:v:/s/ChefCoreC/EU3h57dCsVFLgdxouRETcJgB8U9AY-I1VIhSUGusCFRJRg?e=u2Q2nU

- AWS with Chef managed DB (deployment)
https://progresssoftware.sharepoint.com/:v:/s/ChefCoreC/EbExR2GAlTxMv0Hl1gDA_mABjE-aQTF_00vmbcFuETYUmQ?e=kdDwOb

- AWS with AWS Managed (Provision)
https://progresssoftware.sharepoint.com/:v:/s/ChefCoreC/EROg1CHNRDtHkp7bqKZdfgsBV3yZsjZJPtHHZ9hcEvxYbw?e=JT4xR6

- AWS with AWS Managed (Deployment)
https://progresssoftware.sharepoint.com/:v:/s/ChefCoreC/EYAVZ92vJLlElfLBtGEm4rcBTIDgAdSwheMLQxCzqmU3nQ?e=N2brI7

- If customer adds none no AWS profile or Bastion IAM Role 
<img width="1792" alt="Screenshot 2023-07-13 at 2 07 29 PM" src="https://github.com/chef/automate/assets/62262938/9478e4ce-717c-4305-b3f8-afe1d4ce0d1a">

- If the Role power is not AdminAccess
<img width="1792" alt="Screenshot 2023-07-11 at 4 43 44 PM" src="https://github.com/chef/automate/assets/62262938/d883bc94-493a-4957-a24e-79e448d68ade">


- SuccessFull Deployment while using AWS Cli with [default] as AWS profile

<img width="1792" alt="Screenshot 2023-07-12 at 1 10 19 PM" src="https://github.com/chef/automate/assets/62262938/29582a93-6b8d-4e2f-914b-c6a8081fd2b1">

- Backup also able to pluck the Reds with IAM Role
<img width="719" alt="Screenshot 2023-07-13 at 8 33 02 PM" src="https://github.com/chef/automate/assets/62262938/67cc3430-866d-4079-bcd7-c1e4e21f2503">



- NFS check passing after picking crews from IAM Role
<img width="1792" alt="Screenshot 2023-07-17 at 1 05 51 PM" src="https://github.com/chef/automate/assets/62262938/42ef6a72-9cb3-4306-88d3-69800f85c9bb">


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


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | e0f18d00a57a56056290bc4b62f531808bdca44f |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/chef-automate/deploys/64ad775d71e0d2000844e7ff |
sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![66.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '66.7%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 66.7% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![66.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '66.7%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 66.7% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![79.2%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '79.2%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 79.2% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![79.2%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '79.2%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 79.2% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![60.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '60.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 60.0% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![73.9%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '73.9%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 73.9% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![73.9%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '73.9%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 73.9% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![73.9%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '73.9%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 73.9% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) [![73.9%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '73.9%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 73.9% Coverage on New Code (is less than 80%)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)

[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057) 0.0% Security Hotspots Reviewed on New Code (is less than 100%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8057)



Patch:
diff --git a/VERSION b/VERSION
index e5abe410c..0b335549c 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-4.7.194
\ No newline at end of file
+4.7.196
\ No newline at end of file
diff --git a/components/automate-cli/cmd/chef-automate/automateHAAwsDeployment.go b/components/automate-cli/cmd/chef-automate/automateHAAwsDeployment.go
index a736482b4..6c6d98016 100644
--- a/components/automate-cli/cmd/chef-automate/automateHAAwsDeployment.go
+++ b/components/automate-cli/cmd/chef-automate/automateHAAwsDeployment.go
@@ -5,6 +5,7 @@ import (
 	"crypto/x509"
 	"encoding/pem"
 	"fmt"
+	"net/http"
 	"os"
 	"path/filepath"
 	"strings"
@@ -12,6 +13,8 @@ import (
 	"github.com/chef/automate/components/automate-cli/pkg/status"
 	"github.com/chef/automate/components/automate-deployment/pkg/toml"
 	"github.com/chef/automate/components/local-user-service/password"
+	"github.com/chef/automate/lib/httputils"
+	"github.com/chef/automate/lib/logger"
 	"github.com/chef/automate/lib/platform/command"
 	"github.com/chef/automate/lib/stringutils"
 	ptoml "github.com/pelletier/go-toml"
@@ -19,19 +22,24 @@ import (
 )
 
 const (
-	DEPLOY    = "deploy"
-	PROVISION = "provision"
+	DEPLOY       = "deploy"
+	PROVISION    = "provision"
+	TOKEN_URL    = "http://169.254.169.254/latest/api/token"
+	METADATA_URL = "http://169.254.169.254/latest/meta-data/iam/info"
 )
 
 type awsDeployment struct {
 	config     AwsConfigToml
 	configPath string
 	AWSConfigIp
+	httpRequestClient httputils.HTTPClient
 }
 
 func newAwsDeployemnt(configPath string) *awsDeployment {
+	log := logger.NewLogrusStandardLogger()
 	return &awsDeployment{
-		configPath: configPath,
+		configPath:        configPath,
+		httpRequestClient: httputils.NewClient(log),
 	}
 }
 
@@ -205,7 +213,10 @@ func (a *awsDeployment) validateConfigFields() *list.List {
 func (a *awsDeployment) validateEnvFields() *list.List {
 	errorList := list.New()
 	if len(a.config.Aws.Config.Profile) < 1 {
-		errorList.PushBack("Invalid or empty aws profile name")
+		err := a.isIamRolePresent()
+		if err != nil {
+			errorList.PushBack("Invalid local AWS Profile name or Bastion IAM role, Please Check your local AWS Profile name or Bastion IAM Role is configured properly")
+		}
 	}
 	if len(a.config.Aws.Config.Region) < 1 {
 		errorList.PushBack("Invalid or empty aws region")
@@ -444,3 +455,21 @@ func (a *awsDeployment) getAwsHAIp() error {
 	a.AWSConfigIp = *ConfigIp
 	return nil
 }
+
+func (a *awsDeployment) isIamRolePresent() error {
+	_, tokenResponseBody, err := a.httpRequestClient.MakeRequestWithHeaders(http.MethodPut, TOKEN_URL, nil, "X-aws-ec2-metadata-token-ttl-seconds", "21600")
+	if err != nil {
+		return fmt.Errorf("error while getting the token value: %v", err)
+	}
+
+	token := string(tokenResponseBody)
+
+	resp, _, err := a.httpRequestClient.MakeRequestWithHeaders(http.MethodGet, METADATA_URL, nil, "X-aws-ec2-metadata-token", token)
+	if err != nil {
+		return fmt.Errorf("error while getting the response for IAM role: %v", err)
+	}
+	if resp.StatusCode != 200 {
+		return errors.New("Please check if Bastion has attached an IAM Role to it")
+	}
+	return nil
+}
diff --git a/components/automate-cli/cmd/chef-automate/initConfigHaTmpl.go b/components/automate-cli/cmd/chef-automate/initConfigHaTmpl.go
index 21a75e243..e816f7fa0 100644
--- a/components/automate-cli/cmd/chef-automate/initConfigHaTmpl.go
+++ b/components/automate-cli/cmd/chef-automate/initConfigHaTmpl.go
@@ -154,7 +154,7 @@ enable_custom_certs = false
 # ============== AWS network Config ============================
 ## === INPUT NEEDED ===
 
-# Eg.: profile = "default"
+# Eg.: profile = "default", Leave this field empty if you have an IAM role attached to the bastion machine.
 profile = ""
 
 # Eg.: region = "us-east-1"
diff --git a/components/automate-cli/cmd/chef-automate/status.go b/components/automate-cli/cmd/chef-automate/status.go
index 2018c904c..1d23a8586 100644
--- a/components/automate-cli/cmd/chef-automate/status.go
+++ b/components/automate-cli/cmd/chef-automate/status.go
@@ -56,6 +56,7 @@ type BeStatusValue struct {
 	process     string
 	upTime      string
 	role        string
+	lag         string
 }
 
 type FeStatus []FeStatusValue
@@ -196,7 +197,8 @@ func executeStatusSummary(cmd *cobra.Command, args []string, statusSummaryCmdFla
 		return err
 	}
 	sshUtil := NewSSHUtil(&SSHConfig{})
-	statusSummary := NewStatusSummary(infra, FeStatus{}, BeStatus{}, 10, time.Second, statusSummaryCmdFlags, sshUtil)
+	remoteCmdExecutor := NewRemoteCmdExecutorWithoutNodeMap(sshUtil, writer)
+	statusSummary := NewStatusSummary(infra, FeStatus{}, BeStatus{}, 10, time.Second, statusSummaryCmdFlags, remoteCmdExecutor)
 	err = statusSummary.Prepare()
 	if err != nil {
 		return err
diff --git a/components/automate-cli/cmd/chef-automate/summary.go b/components/automate-cli/cmd/chef-automate/summary.go
index 1f60b4bda..8863f80c0 100644
--- a/components/automate-cli/cmd/chef-automate/summary.go
+++ b/components/automate-cli/cmd/chef-automate/summary.go
@@ -4,6 +4,7 @@ import (
 	"container/list"
 	"encoding/json"
 	"fmt"
+	"regexp"
 	"strconv"
 	"strings"
 	"time"
@@ -30,6 +31,7 @@ const (
 	initialHealth               = "ERROR"
 	initialFormattedDuration    = "0d 0h 0m 0s"
 	initialRole                 = "Unknown"
+	initialLag                  = "NA"
 	defaultServiceDetails       = "DefaultServiceDetails"
 	defaultServiceHealthDetails = "DefaultServiceHealthDetails"
 	censusDetails               = "CensusDetails"
@@ -52,7 +54,7 @@ type Summary struct {
 	spinnerTimeout        time.Duration
 	infra                 *AutomateHAInfraDetails
 	statusSummaryCmdFlags *StatusSummaryCmdFlags
-	sshUtil               SSHUtil
+	remoteCmdExecutor     RemoteCmdExecutor
 }
 
 type A2haHabitatAutoTfvars struct {
@@ -60,7 +62,7 @@ type A2haHabitatAutoTfvars struct {
 	HabSupRingKey              string `json:"hab_sup_ring_key"`
 }
 
-func NewStatusSummary(infra *AutomateHAInfraDetails, feStatus FeStatus, beStatus BeStatus, timeout int64, spinnerTimeout time.Duration, flags *StatusSummaryCmdFlags, sshUtil SSHUtil) StatusSummary {
+func NewStatusSummary(infra *AutomateHAInfraDetails, feStatus FeStatus, beStatus BeStatus, timeout int64, spinnerTimeout time.Duration, flags *StatusSummaryCmdFlags, remoteCmdExecutor RemoteCmdExecutor) StatusSummary {
 	return &Summary{
 		feStatus:              feStatus,
 		beStatus:              beStatus,
@@ -68,7 +70,7 @@ func NewStatusSummary(infra *AutomateHAInfraDetails, feStatus FeStatus, beStatus
 		spinnerTimeout:        spinnerTimeout,
 		infra:                 infra,
 		statusSummaryCmdFlags: flags,
-		sshUtil:               sshUtil,
+		remoteCmdExecutor:     remoteCmdExecutor,
 	}
 }
 
@@ -196,6 +198,7 @@ func (ss *Summary) automateNodeMap(automateIps []string) *NodeTypeAndCmd {
 	return automateNodeMap
 }
 
+// returns automateIps, chefServerIps, opensearchIps, postgresqlIps, errList
 func (ss *Summary) getIPAddressesFromFlagOrInfra() ([]string, []string, []string, []string, *list.List) {
 	errorList := list.New()
 	if ss.statusSummaryCmdFlags.node != "" {
@@ -343,8 +346,7 @@ func (ss *Summary) prepareBEScript(serviceIps []string, nodeMap *NodeTypeAndCmd,
 		nodeMap.Postgresql.CmdInputs.MutipleCmdWithArgs = script
 	}
 
-	cmdUtil := NewRemoteCmdExecutor(nodeMap, ss.sshUtil, writer)
-	beOutput, err := cmdUtil.Execute()
+	beOutput, err := ss.remoteCmdExecutor.ExecuteWithNodeMap(nodeMap)
 	if err != nil {
 		return err
 	}
@@ -358,7 +360,6 @@ func (ss *Summary) prepareBEScript(serviceIps []string, nodeMap *NodeTypeAndCmd,
 }
 
 func (ss *Summary) prepareFEScript(serviceIps []string, nodeMap *NodeTypeAndCmd, serviceName, serviceType string) error {
-	cmdUtil := NewRemoteCmdExecutor(nodeMap, ss.sshUtil, writer)
 
 	// Status Script
 	status := GenerateOriginalAutomateCLICommand(
@@ -392,7 +393,7 @@ func (ss *Summary) prepareFEScript(serviceIps []string, nodeMap *NodeTypeAndCmd,
 		nodeMap.ChefServer.CmdInputs.MutipleCmdWithArgs = script
 	}
 
-	feOutput, err := cmdUtil.Execute()
+	feOutput, err := ss.remoteCmdExecutor.ExecuteWithNodeMap(nodeMap)
 	if err != nil {
 		return err
 	}
@@ -431,6 +432,7 @@ func (ss *Summary) getBEStatus(outputs []*CmdResult, ip string, authToken, servi
 		process:     fmt.Sprintf("%s (pid: %s)", initialServiceState, initialServicePid),
 		upTime:      initialFormattedDuration,
 		role:        initialRole,
+		lag:         initialLag,
 	}
 
 	for _, output := range outputs {
@@ -451,6 +453,11 @@ func (ss *Summary) getBEStatus(outputs []*CmdResult, ip string, authToken, servi
 		return defaultBeStatusValue
 	}
 
+	lag, err := ss.getFollowerLag(cmdResMap[defaultServiceHealthDetails].Output, serviceName, role)
+	if err != nil {
+		lag = "Error"
+	}
+
 	return BeStatusValue{
 		serviceName: serviceName,
 		ipAddress:   ip,
@@ -458,6 +465,7 @@ func (ss *Summary) getBEStatus(outputs []*CmdResult, ip string, authToken, servi
 		process:     fmt.Sprintf("%s (pid: %s)", serviceState, servicePid),
 		upTime:      formattedDuration,
 		role:        role,
+		lag:         lag,
 	}
 }
 
@@ -516,6 +524,30 @@ func (ss *Summary) getBECensus(output, service, memeberId string) (string, error
 	return role, nil
 }
 
+func (ss *Summary) getFollowerLag(output, service, role string) (string, error) {
+	lag := initialLag
+	outputMap, err := parseStringInToMapStringInterface(output)
+	if err != nil {
+		return lag, err
+	}
+
+	if service == postgresql {
+		if role == "Follower" {
+			// Define the regular expression pattern to match the substring
+			pattern := `(\d+ bytes and \d+ seconds)`
+
+			// Compile the regular expression pattern
+			regExp := regexp.MustCompile(pattern)
+
+			// Find the first matching substring of the stdout string
+			lag = regExp.FindString(outputMap["stdout"].(string))
+
+			return lag, nil
+		}
+	}
+	return lag, nil
+}
+
 func (ss *Summary) getFEStatus(ip string, outputs []*CmdResult, serviceType string) FeStatusValue {
 	var osStatus, status string
 
@@ -535,12 +567,13 @@ func (ss *Summary) getFEStatus(ip string, outputs []*CmdResult, serviceType stri
 		}
 	}
 
-	return FeStatusValue{
+	feStatusValue := FeStatusValue{
 		serviceName: serviceType,
 		ipAddress:   ip,
 		status:      status,
 		Opensearch:  osStatus,
 	}
+	return feStatusValue
 }
 
 func (ss *Summary) opensearchStatusInFE(osStatusOutput *CmdResult) string {
@@ -630,9 +663,9 @@ func (ss *Summary) ShowBEStatus() string {
 		tTemp := table.Table{}
 		tTemp.Render()
 		for _, status := range ss.beStatus {
-			t.AppendRow(table.Row{status.serviceName, status.ipAddress, status.health, status.process, status.upTime, status.role})
+			t.AppendRow(table.Row{status.serviceName, status.ipAddress, status.health, status.process, status.lag, status.upTime, status.role})
 		}
-		t.AppendHeader(table.Row{"Name", "IP Address", "Health", "Process", "Uptime", "Role"})
+		t.AppendHeader(table.Row{"Name", "IP Address", "Health", "Process", "Lag", "Uptime", "Role"})
 		return t.Render()
 	}
 	return ""
diff --git a/components/automate-cli/pkg/verifyserver/models/batchcheck.go b/components/automate-cli/pkg/verifyserver/models/batchcheck.go
index f855bb31f..d0ba3043a 100644
--- a/components/automate-cli/pkg/verifyserver/models/batchcheck.go
+++ b/components/automate-cli/pkg/verifyserver/models/batchcheck.go
@@ -87,6 +87,7 @@ type ExternalPG struct {
 type Config struct {
 	SSHUser         *SSHUser       `json:"ssh_user"`
 	Arch            string         `json:"arch"`
+	Profile         string         `json:"profile"`
 	Backup          *Backup        `json:"backup"`
 	Hardware        *Hardware      `json:"hardware"`
 	ExternalDbType  string         `json:"external_db_type"`
@@ -280,14 +281,19 @@ func (c *Config) populateAwsS3BucketName(haConfig *config.HaDeployConfig) {
 				BucketName: haConfig.Architecture.Aws.S3BucketName,
 			},
 		}
-		cred := credentials.NewSharedCredentials("", "")
-		creds, err := cred.Get()
-		if err != nil {
-			log.Println("populateAwsS3BucketName:", err)
-		}
-		c.Backup.ObjectStorage.AccessKey = creds.AccessKeyID
-		c.Backup.ObjectStorage.SecretKey = creds.SecretAccessKey
 		c.Backup.ObjectStorage.AWSRegion = haConfig.Aws.Config.Region
+
+		if haConfig.Aws.Config.Profile != "" {
+			cred := credentials.NewSharedCredentials("", "")
+			creds, err := cred.Get()
+			if err != nil {
+				log.Println("populateAwsS3BucketName:", err)
+			}
+
+			c.Backup.ObjectStorage.AccessKey = creds.AccessKeyID
+			c.Backup.ObjectStorage.SecretKey = creds.SecretAccessKey
+		}
+
 	}
 }
 
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger.go
index c3b2fdbd9..204237768 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger.go
@@ -33,7 +33,7 @@ func (svc *S3BackupConfigCheck) Run(config *models.Config) []models.CheckTrigger
 		return s3ConfigSkippedResponse(config, constants.S3_BACKUP_CONFIG, constants.SKIP_BACKUP_TEST_MESSAGE_S3)
 	}
 
-	if isObjectStorage(config.Backup) {
+	if !isObjectStorage(config ) {
 		return emptyResp(config, constants.S3_BACKUP_CONFIG)
 	}
 
@@ -102,10 +102,17 @@ func getS3CheckRequest(object *models.ObjectStorage) models.S3ConfigRequest {
 	}
 }
 
-func isObjectStorage(backup *models.Backup) bool {
-	return backup.ObjectStorage.BucketName == "" ||
-		backup.ObjectStorage.AccessKey == "" ||
-		backup.ObjectStorage.SecretKey == ""
+func isObjectStorage(config *models.Config) bool {
+	backup := config.Backup
+	if backup.ObjectStorage.BucketName == "" {
+		return false
+	} else if config.Profile != "" {
+		if backup.ObjectStorage.AccessKey == "" ||
+			backup.ObjectStorage.SecretKey == "" {
+			return false
+		}
+	}
+	return true
 }
 
 func emptyResp(config *models.Config, checktype string) []models.CheckTriggerResponse {
diff --git a/components/automate-cli/pkg/verifyserver/utils/awsutils/aws.go b/components/automate-cli/pkg/verifyserver/utils/awsutils/aws.go
index 54884c868..1a2b11c91 100644
--- a/components/automate-cli/pkg/verifyserver/utils/awsutils/aws.go
+++ b/components/automate-cli/pkg/verifyserver/utils/awsutils/aws.go
@@ -35,7 +35,9 @@ func (au *AwsUtilsImpl) NewSessionWithOptions(endpoint, accessKey, secretKey, re
 	}
 	config.Endpoint = &endpoint
 	config.Region = aws.String(region)
-	config.Credentials = credentials.NewStaticCredentials(accessKey, secretKey, "")
+	if accessKey != "" && secretKey != "" {
+		config.Credentials = credentials.NewStaticCredentials(accessKey, secretKey, "")
+	}
 	return session.NewSessionWithOptions(session.Options{
 		Config: config,
 	})
diff --git a/components/docs-chef-io/content/automate/ha_aws_deploy_steps.md b/components/docs-chef-io/content/automate/ha_aws_deploy_steps.md
index caf8f8530..fa2c38346 100644
--- a/components/docs-chef-io/content/automate/ha_aws_deploy_steps.md
+++ b/components/docs-chef-io/content/automate/ha_aws_deploy_steps.md
@@ -110,7 +110,7 @@ Run the following steps on Bastion Host Machine:
     - If you don't have a custom FQDN leave `fqdn` as empty for this AWS deployment. By default, AWS Application load balancer will be used as `fqdn`.
     - Set `instance_count` for Chef Automate, Chef Infra Server, Postgresql, OpenSearch.
     - Set AWS Config Details:
-        - Set `profile`, by default `profile` is `"default"`
+        - Set the AWS `profile`. In case you attached the IAM role to the bastion machine, leave this field empty.
         - Set `region`, by default `region` is `"us-east-1"`
         - Set `aws_vpc_id`, which you had created as Prerequisite step. Example: `"vpc12318h"`
         - Set `private_custom_subnets` to the 3 private subnets we created in prerequisites step and set `public_custom_subnets` to the 3 public subnets we created in prerequisites step: example : `["subnet-07e469d218301533","subnet-07e469d218041534","subnet-07e469d283041535"]`
@@ -161,7 +161,8 @@ Run the following steps on Bastion Host Machine:
     ```
 
 1. After the deployment successfully completed. To view the automate UI, run the command `chef-automate info`, you will get the `automate_url`.
-   If we want to change the FQDN URL from the loadbalancer URL to some other FQDN URL, then use below template
+  If you want to change the FQDN URL from the loadbalancer URL to some other FQDN URL, then use below template
+
 
 -   create a file `a2.fqdn.toml`
 
diff --git a/components/docs-chef-io/content/automate/ha_aws_managed_deploy_steps.md b/components/docs-chef-io/content/automate/ha_aws_managed_deploy_steps.md
index e5665cb98..bea25bf6b 100644
--- a/components/docs-chef-io/content/automate/ha_aws_managed_deploy_steps.md
+++ b/components/docs-chef-io/content/automate/ha_aws_managed_deploy_steps.md
@@ -110,7 +110,7 @@ Set the above prerequisites in `~/.aws/credentials` in Bastion Host:
    - Set `backup_config` to `"s3"` or `efs`.
    - If `backup_config` is `s3`, uncomment and set the value for following `s3_bucketName` attribute to your bucket name. If the bucket name does not exist, it will be created for you automatically.
    - Set `admin_password` to access Chef Automate UI for user `admin`.
-   - Don't set `fqdn` for the AWS deployment.
+   - If you don't have a custom FQDN leave `fqdn` as empty for this AWS deployment. By default, AWS Application load balancer will be used as `fqdn`.
    - Set `instance_count` for *Chef Automate*, *Chef Infra Server*, *Postgresql*, *OpenSearch*.
    - Set AWS Config Details:
       - Set `profile`. The default value of `profile` is `"default"`.
@@ -153,6 +153,13 @@ Set the above prerequisites in `~/.aws/credentials` in Bastion Host:
 
    #Run provision command to deploy `automate.aib` with set `config.toml`
    chef-automate provision-infra config.toml --airgap-bundle automate.aib
+    "
+    ```
+
+1. Once the provisioning is successful, **if you have added custom DNS to your configuration file (`fqdn`), make sure to map the load-balancer FQDN from the output of previous command to your DNS from DNS Provider**. After that continue with the deployment process with following.
+
+    ```bash
+    sudo -- sh -c "
 
    #Run deploy command to deploy `automate.aib` with set `config.toml`
    chef-automate deploy config.toml --airgap-bundle automate.aib
@@ -166,7 +173,7 @@ Set the above prerequisites in `~/.aws/credentials` in Bastion Host:
    ```
 
 1. After the deployment successfully completed. To view the automate UI, run the command `chef-automate info`, you will get the `automate_url`.
-  If we want to change the FQDN URL from the loadbalancer URL to some other FQDN URL, then use below template
+  If you want to change the FQDN URL from the loadbalancer URL to some other FQDN URL, then use below template
   
 - Create a file `a2.fqdn.toml`
 
diff --git a/dev/populate_chef_backend_data.sh b/dev/populate_chef_backend_data.sh
index 64c973390..a5c84744e 100644
--- a/dev/populate_chef_backend_data.sh
+++ b/dev/populate_chef_backend_data.sh
@@ -58,7 +58,7 @@ do
   for file in *; 
   do
     # Extract the contents of the tar file
-    knife upload file -s $SERVER_URL/organizations/"org$i" --config-option cookbook_path=/home/ubuntu/cookbook
+    knife upload $file -s $SERVER_URL/organizations/"org$i" --config-option cookbook_path=/home/ubuntu/cookbook
   done
 done
 
diff --git a/lib/config/hadeployconfigverify.go b/lib/config/hadeployconfigverify.go
index 97a50aa5e..c46f0f67c 100644
--- a/lib/config/hadeployconfigverify.go
+++ b/lib/config/hadeployconfigverify.go
@@ -595,11 +595,7 @@ func validateAwsManagedServices(aws *ConfigAwsSettings) error {
 
 func validateCommonAwsSettings(aws *ConfigAwsSettings) error {
 	errorList := list.New()
-
-	if err := validateRequiredString(aws.Profile, "aws profile name"); err != nil {
-		errorList.PushBack(err)
-	}
-
+	
 	if err := validateRequiredString(aws.Region, "aws region"); err != nil {
 		errorList.PushBack(err)
 	}
diff --git a/lib/httputils/http.go b/lib/httputils/http.go
index 54d3fc826..e40093348 100644
--- a/lib/httputils/http.go
+++ b/lib/httputils/http.go
@@ -14,6 +14,7 @@ import (
 // HTTPClient interface represents an HTTP client.
 type HTTPClient interface {
 	MakeRequest(requestMethod, url string, body interface{}) (*http.Response, []byte, error)
+	MakeRequestWithHeaders(requestMethod, url string, body interface{}, headerkey string, headerValue string) (*http.Response, []byte, error)
 }
 
 // Client is a wrapper around http.Client that adds some convenience methods for making requests and handling responses.
@@ -24,13 +25,18 @@ type Client struct {
 
 // MockHTTPClient is a mock implementation of HTTPClient.
 type MockHTTPClient struct {
-	MakeRequestFunc func(requestMethod, url string, body interface{}) (*http.Response, []byte, error)
+	MakeRequestFunc            func(requestMethod, url string, body interface{}) (*http.Response, []byte, error)
+	MakeRequestWithHeadersfunc func(requestMethod, url string, body interface{}, headerkey string, headerValue string) (*http.Response, []byte, error)
 }
 
 func (m *MockHTTPClient) MakeRequest(requestMethod, url string, body interface{}) (*http.Response, []byte, error) {
 	return m.MakeRequestFunc(requestMethod, url, body)
 }
 
+func (m *MockHTTPClient) MakeRequestWithHeaders(requestMethod, url string, body interface{}, headerkey string, headerValue string) (*http.Response, []byte, error) {
+	return m.MakeRequestWithHeadersfunc(requestMethod, url, body, headerkey, headerValue)
+}
+
 // NewClient returns a new Client with sane defaults.
 func NewClient(logger logger.Logger) *Client {
 	return &Client{
@@ -85,3 +91,39 @@ func (c *Client) MakeRequest(requestMethod, url string, body interface{}) (*http
 	c.Logger.Debugf("Response body for MakeRequest: \n%s\n", string(responseBody))
 	return resp, responseBody, nil
 }
+
+func (c *Client) MakeRequestWithHeaders(requestMethod, url string, body interface{}, headerKey string, headerValue string) (*http.Response, []byte, error) {
+	var reader io.Reader
+
+	// Marshal the request body to JSON if it's not nil
+	if body != nil {
+		requestBody, err := json.Marshal(body)
+		if err != nil {
+			return nil, nil, fmt.Errorf("failed to marshal request body: %w", err)
+		}
+		c.Logger.Debugf("Request body for MakeRequest: \n%s\n", string(requestBody))
+		reader = bytes.NewReader(requestBody)
+	}
+
+	req, err := http.NewRequest(requestMethod, url, reader)
+	if err != nil {
+		return nil, nil, fmt.Errorf("failed to create HTTP request: %w", err)
+	}
+
+	req.Header.Set(headerKey, headerValue)
+
+	resp, err := c.Client.Do(req)
+	if err != nil {
+		return nil, nil, fmt.Errorf("failed to make HTTP request: %w", err)
+	}
+
+	defer resp.Body.Close()
+
+	responseBody, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return nil, nil, fmt.Errorf("failed to read response body: %w", err)
+	}
+
+	c.Logger.Debugf("Response body for MakeRequest: \n%s\n", string(responseBody))
+	return resp, responseBody, nil
+}
diff --git a/terraform/a2ha-terraform/modules/aws_metadata/main.tf b/terraform/a2ha-terraform/modules/aws_metadata/main.tf
index 411d5a67b..1a3c31053 100644
--- a/terraform/a2ha-terraform/modules/aws_metadata/main.tf
+++ b/terraform/a2ha-terraform/modules/aws_metadata/main.tf
@@ -15,3 +15,10 @@ data "http" "getEc2PrivateIP" {
     X-aws-ec2-metadata-token = chomp(data.local_file.readToken.content)
   }
 }
+
+data "http" "getBastionRole" {
+  url = "http://169.254.169.254/latest/meta-data/iam/info"
+  request_headers = {
+    X-aws-ec2-metadata-token = chomp(data.local_file.readToken.content)
+  }
+}
diff --git a/terraform/a2ha-terraform/modules/aws_metadata/output.tf b/terraform/a2ha-terraform/modules/aws_metadata/output.tf
index 4209b78bb..e606c7b8c 100644
--- a/terraform/a2ha-terraform/modules/aws_metadata/output.tf
+++ b/terraform/a2ha-terraform/modules/aws_metadata/output.tf
@@ -1,3 +1,7 @@
 output "json_data" {
   value = "${data.http.getEc2PrivateIP.response_body}/32"
 }
+
+output "bastion_role" {
+  value = "${data.http.getBastionRole.status_code}"
+}
diff --git a/terraform/a2ha-terraform/reference_architectures/aws/variables.tf b/terraform/a2ha-terraform/reference_architectures/aws/variables.tf
index cacbde55f..880942e6d 100644
--- a/terraform/a2ha-terraform/reference_architectures/aws/variables.tf
+++ b/terraform/a2ha-terraform/reference_architectures/aws/variables.tf
@@ -51,7 +51,7 @@ variable "aws_os_snapshot_role_arn" {
 }
 
 variable "aws_profile" {
-  default     = "default"
+  default     = ""
   description = "The AWS profile to use from your ~/.aws/credentials file."
 }
 


Test patch:
diff --git a/components/automate-cli/cmd/chef-automate/automateHAAwsDeployment_test.go b/components/automate-cli/cmd/chef-automate/automateHAAwsDeployment_test.go
new file mode 100644
index 000000000..4d010f8f9
--- /dev/null
+++ b/components/automate-cli/cmd/chef-automate/automateHAAwsDeployment_test.go
@@ -0,0 +1,106 @@
+package main
+
+import (
+	"net/http"
+	"testing"
+
+	"github.com/chef/automate/lib/httputils"
+	"github.com/pkg/errors"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestGetBastionIamRole(t *testing.T) {
+	ser := newAwsDeployemnt("")
+	tests := []struct {
+		description        string
+		MockhttputilsToken httputils.HTTPClient
+		MockhttputilsIam   httputils.HTTPClient
+		wantError          error
+		testurl            string
+	}{
+		{
+			description: "Failed to get token value from the request",
+			MockhttputilsToken: &httputils.MockHTTPClient{
+				MakeRequestWithHeadersfunc: func(requestMethod, url string, body interface{}, headerkey, headerValue string) (*http.Response, []byte, error) {
+					return nil, nil, errors.New("failed to marshal request body")
+				},
+			},
+			wantError: errors.New("error while getting the token value: failed to marshal request body"),
+			testurl:   TOKEN_URL,
+		},
+		{
+			description: "Failed to get token value from the request (error in creation of request)",
+			MockhttputilsToken: &httputils.MockHTTPClient{
+				MakeRequestWithHeadersfunc: func(requestMethod, url string, body interface{}, headerkey, headerValue string) (*http.Response, []byte, error) {
+					return nil, nil, errors.New("failed to create HTTP request")
+				},
+			},
+			wantError: errors.New("error while getting the token value: failed to create HTTP request"),
+			testurl:   TOKEN_URL,
+		},
+		{
+			description: "Bastion IAM role is not attached",
+			MockhttputilsToken: &httputils.MockHTTPClient{
+				MakeRequestWithHeadersfunc: func(requestMethod, url string, body interface{}, headerkey, headerValue string) (*http.Response, []byte, error) {
+					return &http.Response{}, nil, nil
+				},
+			},
+			MockhttputilsIam: &httputils.MockHTTPClient{
+				MakeRequestWithHeadersfunc: func(requestMethod, url string, body interface{}, headerkey, headerValue string) (*http.Response, []byte, error) {
+					return &http.Response{}, []byte("Success"), nil
+				},
+			},
+			wantError: errors.New("Please check if Bastion has attached an IAM Role to it"),
+			testurl:   METADATA_URL,
+		},
+		{
+			description: "Bastion IAM role is not attached (Error)",
+			MockhttputilsToken: &httputils.MockHTTPClient{
+				MakeRequestWithHeadersfunc: func(requestMethod, url string, body interface{}, headerkey, headerValue string) (*http.Response, []byte, error) {
+					return &http.Response{}, nil, nil
+				},
+			},
+			MockhttputilsIam: &httputils.MockHTTPClient{
+				MakeRequestWithHeadersfunc: func(requestMethod, url string, body interface{}, headerkey, headerValue string) (*http.Response, []byte, error) {
+					if requestMethod == http.MethodPut {
+						return nil, nil, nil
+					}
+					return nil, nil, errors.New("failed to Make HTTP Request")
+				},
+			},
+			wantError: errors.New("error while getting the response for IAM role: failed to Make HTTP Request"),
+			testurl:   METADATA_URL,
+		},
+		{
+			description: "Bastion IAM role is attached",
+			MockhttputilsToken: &httputils.MockHTTPClient{
+				MakeRequestWithHeadersfunc: func(requestMethod, url string, body interface{}, headerkey, headerValue string) (*http.Response, []byte, error) {
+					return &http.Response{}, nil, nil
+				},
+			},
+			MockhttputilsIam: &httputils.MockHTTPClient{
+				MakeRequestWithHeadersfunc: func(requestMethod, url string, body interface{}, headerkey, headerValue string) (*http.Response, []byte, error) {
+					return &http.Response{
+						StatusCode: 200,
+					}, []byte("Success"), nil
+				},
+			},
+			wantError: nil,
+			testurl:   METADATA_URL,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.description, func(t *testing.T) {
+			if tt.testurl == TOKEN_URL {
+				ser.httpRequestClient = tt.MockhttputilsToken
+			} else if tt.testurl == METADATA_URL {
+				ser.httpRequestClient = tt.MockhttputilsIam
+			}
+			err := ser.isIamRolePresent()
+			if err != nil {
+				assert.Equal(t, err.Error(), tt.wantError.Error())
+			}
+		})
+	}
+}
diff --git a/components/automate-cli/cmd/chef-automate/summary_test.go b/components/automate-cli/cmd/chef-automate/summary_test.go
index 25ffdd136..7ba3456ef 100644
--- a/components/automate-cli/cmd/chef-automate/summary_test.go
+++ b/components/automate-cli/cmd/chef-automate/summary_test.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"errors"
 	"fmt"
 	"strings"
 	"testing"
@@ -27,13 +28,17 @@ Incorrect postgresql IP, 127.0.0 IP address validation failed
 Incorrect postgresql IP, 127.0.1 IP address validation failed
 Incorrect postgresql IP, 127.0.2 IP address validation failed
 Incorrect postgresql IP, 127.0.3 IP address validation failed`
-	displayBE = `+------------+--------------+--------+--------------+-------------+---------+
-| NAME       | IP ADDRESS   | HEALTH | PROCESS      | UPTIME      | ROLE    |
-+------------+--------------+--------+--------------+-------------+---------+
-| postgresql | 198.51.100.7 | ERROR  | down (pid: ) | 0d 0h 0m 0s | Unknown |
-+------------+--------------+--------+--------------+-------------+---------+`
-	displayFEAutomate         = `| automate    | 198.51.100.1 | ERROR  | Unknown    |`
-	displayFECS               = `| chef-server | 198.51.100.2 | ERROR  | Unknown    |`
+	displayBE = `+------------+--------------+--------+--------------+-----+-------------+---------+
+| NAME       | IP ADDRESS   | HEALTH | PROCESS      | LAG | UPTIME      | ROLE    |
++------------+--------------+--------+--------------+-----+-------------+---------+
+| postgresql | 198.51.100.7 | ERROR  | down (pid: ) | NA  | 0d 0h 0m 0s | Unknown |
++------------+--------------+--------+--------------+-----+-------------+---------+`
+	pgFollowerNode = `+------------+--------------+--------+----------------+-----------------------+---------------+----------+
+| NAME       | IP ADDRESS   | HEALTH | PROCESS        | LAG                   | UPTIME        | ROLE     |
++------------+--------------+--------+----------------+-----------------------+---------------+----------+
+| postgresql | 198.51.100.7 | OK     | up (pid: 2760) | 0 bytes and 1 seconds |`
+	displayFEAutomate         = `| automate    | 198.51.100.1 | OK     | "green" (Active: 100.0) |`
+	displayFECS               = `| chef-server | 198.51.100.2 | OK     | "green" (Active: 100.0) |`
 	mockA2haHabitatAutoTfvars = "../../pkg/testfiles/a2ha_habitat.auto.tfvars"
 )
 
@@ -43,7 +48,11 @@ func TestCheckIPAddressesFromInfra(t *testing.T) {
 	infra.Outputs.ChefServerPrivateIps.Value = []string{ValidIP2, ValidIP3}
 	infra.Outputs.OpensearchPrivateIps.Value = []string{ValidIP4, ValidIP5, ValidIP6}
 	infra.Outputs.PostgresqlPrivateIps.Value = []string{ValidIP7, ValidIP8, ValidIP9}
-	ss := NewStatusSummary(infra, FeStatus{}, BeStatus{}, 10, time.Second, &StatusSummaryCmdFlags{}, getMockSSHUtilRunSummary(&SSHConfig{}, nil, nil))
+	ss := NewStatusSummary(infra, FeStatus{}, BeStatus{}, 10, time.Second, &StatusSummaryCmdFlags{}, &MockRemoteCmdExecutor{
+		ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+			return nil, nil
+		},
+	})
 
 	automateIps, chefServerIps, opensearchIps, postgresqlIps, errList := ss.(*Summary).getIPAddressesFromFlagOrInfra()
 	assert.Equal(t, errList.Len(), 0)
@@ -66,7 +75,11 @@ func TestCheckIPAddressesByServicesAndIpFromFlag(t *testing.T) {
 		isChefServer: true,
 		isOpenSearch: true,
 		isPostgresql: true,
-	}, getMockSSHUtilRunSummary(&SSHConfig{}, nil, nil))
+	}, &MockRemoteCmdExecutor{
+		ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+			return nil, nil
+		},
+	})
 
 	automateIps, chefServerIps, opensearchIps, postgresqlIps, errList := ss.(*Summary).getIPAddressesFromFlagOrInfra()
 	assert.Equal(t, errList.Len(), 0)
@@ -88,7 +101,11 @@ func TestCheckIPAddressesOnlyByServices(t *testing.T) {
 		isChefServer: true,
 		isOpenSearch: true,
 		isPostgresql: true,
-	}, getMockSSHUtilRunSummary(&SSHConfig{}, nil, nil))
+	}, &MockRemoteCmdExecutor{
+		ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+			return nil, nil
+		},
+	})
 
 	automateIps, chefServerIps, opensearchIps, postgresqlIps, errList := ss.(*Summary).getIPAddressesFromFlagOrInfra()
 	assert.Equal(t, errList.Len(), 0)
@@ -111,7 +128,11 @@ func TestCheckIPAddressesError(t *testing.T) {
 		isChefServer: true,
 		isOpenSearch: true,
 		isPostgresql: true,
-	}, getMockSSHUtilRunSummary(&SSHConfig{}, nil, nil))
+	}, &MockRemoteCmdExecutor{
+		ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+			return nil, nil
+		},
+	})
 
 	_, _, _, _, errList := ss.(*Summary).getIPAddressesFromFlagOrInfra()
 	assert.Equal(t, errList.Len(), 1)
@@ -131,7 +152,11 @@ func TestCheckIPAddressesValidation(t *testing.T) {
 		isChefServer: true,
 		isOpenSearch: true,
 		isPostgresql: true,
-	}, getMockSSHUtilRunSummary(&SSHConfig{}, nil, nil))
+	}, &MockRemoteCmdExecutor{
+		ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+			return nil, nil
+		},
+	})
 
 	automateIps, chefServerIps, opensearchIps, postgresqlIps, errList := ss.(*Summary).getIPAddressesFromFlagOrInfra()
 	assert.Equal(t, errList.Len(), 16)
@@ -141,13 +166,57 @@ func TestCheckIPAddressesValidation(t *testing.T) {
 	assert.Equal(t, postgresqlIps, []string(nil))
 	assert.Contains(t, getSingleErrorFromList(errList).Error(), invalidIpAddress)
 }
+
+// {OsStatus 10.0.192.172 []  <nil>}
 func TestRunFENodeDiaplay(t *testing.T) {
 	a2haHabitatAutoTfvars = mockA2haHabitatAutoTfvars
 	infra := &AutomateHAInfraDetails{}
 	infra.Outputs.AutomatePrivateIps.Value = []string{ValidIP1}
 	infra.Outputs.ChefServerPrivateIps.Value = []string{ValidIP2}
-	sshUtil := getMockSSHUtilRunSummary(&SSHConfig{}, nil, nil)
-	ss := NewStatusSummary(infra, FeStatus{}, BeStatus{}, 10, time.Second, &StatusSummaryCmdFlags{}, sshUtil)
+	ss := NewStatusSummary(infra, FeStatus{}, BeStatus{}, 10, time.Second, &StatusSummaryCmdFlags{}, &MockRemoteCmdExecutor{
+		ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+			if strings.Contains(strings.Join(nodeMap.Automate.CmdInputs.NodeIps, ","), ValidIP1) {
+
+				return map[string][]*CmdResult{
+					ValidIP1: {
+						&CmdResult{
+							ScriptName:  "OsStatus",
+							HostIP:      ValidIP1,
+							OutputFiles: []string{},
+							Error:       nil,
+							Output:      `{"cluster_name":"opensearch","status":"green","timed_out":false,"number_of_nodes":3,"number_of_data_nodes":3,"discovered_master":true,"active_primary_shards":35,"active_shards":74,"relocating_shards":0,"initializing_shards":0,"unassigned_shards":0,"delayed_unassigned_shards":0,"number_of_pending_tasks":0,"number_of_in_flight_fetch":0,"task_max_waiting_in_queue_millis":0,"active_shards_percent_as_number":100.0}`,
+						},
+						&CmdResult{
+							ScriptName:  "Status",
+							HostIP:      ValidIP1,
+							OutputFiles: []string{},
+							Error:       nil,
+							Output:      ``,
+						},
+					},
+				}, nil
+				// displayFEAutomate, nil
+			}
+			return map[string][]*CmdResult{
+				ValidIP2: {
+					&CmdResult{
+						ScriptName:  "OsStatus",
+						HostIP:      ValidIP2,
+						OutputFiles: []string{},
+						Error:       nil,
+						Output:      `{"cluster_name":"opensearch","status":"green","timed_out":false,"number_of_nodes":3,"number_of_data_nodes":3,"discovered_master":true,"active_primary_shards":35,"active_shards":74,"relocating_shards":0,"initializing_shards":0,"unassigned_shards":0,"delayed_unassigned_shards":0,"number_of_pending_tasks":0,"number_of_in_flight_fetch":0,"task_max_waiting_in_queue_millis":0,"active_shards_percent_as_number":100.0}`,
+					},
+					&CmdResult{
+						ScriptName:  "Status",
+						HostIP:      ValidIP2,
+						OutputFiles: []string{},
+						Error:       nil,
+						Output:      ``,
+					},
+				},
+			}, nil
+		},
+	})
 	err := ss.Prepare()
 	assert.NoError(t, err)
 	fe := ss.ShowFEStatus()
@@ -155,22 +224,6 @@ func TestRunFENodeDiaplay(t *testing.T) {
 	assert.Contains(t, fe, displayFECS)
 
 }
-func TestRunBENodeDiaplay(t *testing.T) {
-	a2haHabitatAutoTfvars = mockA2haHabitatAutoTfvars
-	infra := &AutomateHAInfraDetails{}
-	// infra.Outputs.OpensearchPrivateIps.Value = []string{ValidIP4, ValidIP5, ValidIP6}
-	infra.Outputs.PostgresqlPrivateIps.Value = []string{ValidIP7}
-	sshUtil := getMockSSHUtilRunSummary(&SSHConfig{hostIP: ValidIP7}, nil, nil)
-
-	ss := NewStatusSummary(infra, FeStatus{}, BeStatus{}, 10, time.Second, &StatusSummaryCmdFlags{}, sshUtil)
-	// Mock the time to a specific time
-	mockTime := time.Date(2023, 3, 15, 12, 0, 0, 0, time.UTC)
-	nowFunc = func() time.Time { return mockTime }
-	err := ss.Prepare()
-	assert.NoError(t, err)
-	be := ss.ShowBEStatus()
-	assert.Equal(t, be, displayBE)
-}
 
 func getMockSSHUtilRunSummary(sshConfig *SSHConfig, CFTRError error, CSECORError error) *MockSSHUtilsImpl {
 	return &MockSSHUtilsImpl{
@@ -266,3 +319,141 @@ func getMockSSHUtilRunSummary(sshConfig *SSHConfig, CFTRError error, CSECORError
 		},
 	}
 }
+
+func TestGetFollowerLag(t *testing.T) {
+	a2haHabitatAutoTfvars = mockA2haHabitatAutoTfvars
+
+	testCases := []struct {
+		description string
+		beOutput    map[string][]*CmdResult
+		expectedErr error
+		ip          string
+		wantErr     bool
+	}{
+		{
+			description: "Showing Lag with No Error for Follower node",
+			beOutput: map[string][]*CmdResult{
+				ValidIP7: {
+					&CmdResult{
+						ScriptName:  censusDetails,
+						HostIP:      ValidIP7,
+						OutputFiles: []string{},
+						Output: `{
+							"changed": false,
+							"census_groups": {
+								"automate-ha-postgresql.default": {
+									"population": {
+										"8cfc79a0be3c4e74ab717bac25a1d185": {
+											"leader": false,
+											"follower": true
+											}
+										}
+									}
+								}
+							}`,
+						Error: nil,
+					},
+					&CmdResult{
+						ScriptName:  defaultServiceDetails,
+						HostIP:      ValidIP7,
+						OutputFiles: []string{},
+						Output: `{
+							"process": { "pid": 2760, "state": "up", "state_entered": 1689602436 },
+							"sys": {
+								"member_id": "8cfc79a0be3c4e74ab717bac25a1d185"
+							}
+						}`,
+						Error: nil,
+					},
+					&CmdResult{
+						ScriptName:  defaultServiceHealthDetails,
+						HostIP:      ValidIP7,
+						OutputFiles: []string{},
+						Output:      `{"status":"OK","stdout":"Primary server is available at 10.0.192.111 with uptime: 0s\nLocal replica 10.0.192.209 is 0 bytes and 1 seconds behind the primary\n","stderr":""}`,
+						Error:       nil,
+					},
+				},
+			},
+			ip:          ValidIP7,
+			expectedErr: nil,
+			wantErr:     false,
+		},
+		{
+			description: "Showing Lag with Parsing Error",
+			beOutput: map[string][]*CmdResult{
+				ValidIP7: {
+					&CmdResult{
+						ScriptName:  censusDetails,
+						HostIP:      ValidIP7,
+						OutputFiles: []string{},
+						Output: `{
+							"changed": false,
+							"census_groups": {
+								"automate-ha-postgresql.default": {
+									"population": {
+										"8cfc79a0be3c4e74ab717bac25a1d185": {
+											"leader": false,
+											"follower": true
+											
+										}
+									}
+								}
+							}`,
+						Error: nil,
+					},
+					&CmdResult{
+						ScriptName:  defaultServiceDetails,
+						HostIP:      ValidIP7,
+						OutputFiles: []string{},
+						Output: `{
+							"process": { "pid": 2760, "state": "up", "state_entered": 1689602436 ,
+							"sys": {
+								"member_id": "8cfc79a0be3c4e74ab717bac25a1d185"
+							}
+						}`,
+						Error: nil,
+					},
+					&CmdResult{
+						ScriptName:  defaultServiceHealthDetails,
+						HostIP:      ValidIP7,
+						OutputFiles: []string{},
+						Output:      `{"status":"OK","stdout":"Primary server is available at 10.0.192.111 with uptime: 0s\nLocal replica 10.0.192.209 is 0 bytes and 1 seconds behind the primary\n","stderr":"}`,
+						Error:       nil,
+					},
+				},
+			},
+			ip:          ValidIP7,
+			expectedErr: errors.New("ERROR"),
+			wantErr:     true,
+		},
+	}
+
+	for _, test := range testCases {
+
+		infra := &AutomateHAInfraDetails{}
+		infra.Outputs.PostgresqlPrivateIps.Value = []string{test.ip}
+		ss := NewStatusSummary(infra, FeStatus{}, BeStatus{}, 10, time.Second, &StatusSummaryCmdFlags{
+			node:         test.ip,
+			isPostgresql: true,
+		}, &MockRemoteCmdExecutor{
+			ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+				return test.beOutput, nil
+			},
+		})
+
+		err := ss.Prepare()
+		assert.NoError(t, err)
+		be := ss.ShowBEStatus()
+
+		if test.wantErr {
+			assert.Contains(t, be, ValidIP7)
+			assert.Contains(t, be, test.expectedErr.Error())
+
+		} else {
+			assert.Contains(t, be, ValidIP7)
+			assert.Contains(t, be, "0 bytes and 1 seconds")
+			assert.Contains(t, be, "up (pid: 2760)")
+			assert.Contains(t, be, "postgresql")
+		}
+	}
+}
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/hardwareresourcechecktrigger/hardwareresourcecountchecktrigger_test.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/hardwareresourcechecktrigger/hardwareresourcecountchecktrigger_test.go
index 6071c13ce..c2455b543 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/hardwareresourcechecktrigger/hardwareresourcecountchecktrigger_test.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/hardwareresourcechecktrigger/hardwareresourcecountchecktrigger_test.go
@@ -295,7 +295,7 @@ func TestHardwareResourceCountCheck_TriggerHardwareResourceCountCheck(t *testing
 	t.Run("cannot reach", func(t *testing.T) {
 		// create the CheckTrigger instance to be tested
 		hrc := HardwareResourceCountCheck{log: logger.NewTestLogger(), httpRequestClient: &httputils.MockHTTPClient{
-			func(requestMethod, url string, body interface{}) (*http.Response, []byte, error) {
+			MakeRequestFunc : func(requestMethod, url string, body interface{}) (*http.Response, []byte, error) {
 				return nil, []byte(""), errors.New("")
 			},
 		},host: "invalid-url"}
diff --git a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger_test.go b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger_test.go
index 987bb3ab3..cb6bc35e2 100644
--- a/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger_test.go
+++ b/components/automate-cli/pkg/verifyserver/services/batchcheckservice/trigger/s3backupchecktrigger/s3backupconfigchecktrigger_test.go
@@ -8,11 +8,10 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/stretchr/testify/assert"
-
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/constants"
 	"github.com/chef/automate/components/automate-cli/pkg/verifyserver/models"
 	"github.com/chef/automate/lib/logger"
+	"github.com/stretchr/testify/assert"
 )
 
 const (
@@ -429,3 +428,60 @@ func TestGetPortsForMockServer(t *testing.T) {
 
 	assert.Equal(t, 0, len(resp))
 }
+
+func TestS3ConfigSkippedResponse(t *testing.T) {
+	type args struct {
+		config    *models.Config
+		checkType string
+	}
+	tests := []struct {
+		name string
+		args args
+		want []models.CheckTriggerResponse
+	}{
+		{
+			name: "Make the skip Response",
+			args: args{
+				config: &models.Config{
+					Hardware: &models.Hardware{
+						AutomateNodeCount:        1,
+						AutomateNodeIps:          []string{constants.LOCALHOST},
+						ChefInfraServerNodeCount: 1,
+						ChefInfraServerNodeIps:   []string{constants.LOCALHOST},
+					},
+				},
+				checkType: "s3-backup-config",
+			},
+			want: []models.CheckTriggerResponse{
+				{
+					NodeType:  "automate",
+					CheckType: "s3-backup-config",
+					Result: models.ApiResult{
+						Passed:      false,
+						Skipped:     true,
+						Check:       "s3-backup-config",
+						SkipMessage: constants.SKIP_BACKUP_TEST_MESSAGE_S3,
+					},
+					Host: constants.LOCALHOST,
+				},
+				{
+					NodeType:  "chef-infra-server",
+					CheckType: "s3-backup-config",
+					Result: models.ApiResult{
+						Passed:      false,
+						Skipped:     true,
+						Check:       "s3-backup-config",
+						SkipMessage: constants.SKIP_BACKUP_TEST_MESSAGE_S3,
+					},
+					Host: constants.LOCALHOST,
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := s3ConfigSkippedResponse(tt.args.config, tt.args.checkType, constants.SKIP_BACKUP_TEST_MESSAGE_S3)
+			assert.Equal(t, tt.want, got)
+		})
+	}
+}
diff --git a/lib/config/hadeployconfigverify_test.go b/lib/config/hadeployconfigverify_test.go
index 22ae5b900..087e584b8 100644
--- a/lib/config/hadeployconfigverify_test.go
+++ b/lib/config/hadeployconfigverify_test.go
@@ -21,7 +21,7 @@ func TestParseAndVerify(t *testing.T) {
 			name:    "Verify AWS Config",
 			args:    args{configFile: "./testdata/HaAws.toml"},
 			wantErr: true,
-			err:     errors.New("invalid or empty: ssh_user\ninvalid or empty: ssh_key_file\ninvalid or empty s3_bucketName\ninvalid or empty: aws profile name\ninvalid or empty: aws region\ninvalid or empty: aws aws_vpc_id\ninvalid or empty: aws private_custom_subnets\ninvalid or empty: aws public_custom_subnets\ninvalid or empty: aws ssh_key_pair_name\ninvalid or empty: aws ami_id\ninvalid or empty: aws automate_server_instance_type\ninvalid or empty: aws automate_lb_certificate_arn\nempty value: aws automate_ebs_volume_iops\nempty value: aws automate_ebs_volume_size\ninvalid or empty: aws automate_ebs_volume_type\nempty value: aws chef_ebs_volume_iops\nempty value: aws chef_ebs_volume_size\ninvalid or empty: aws chef_ebs_volume_type\ninvalid or empty: aws chef_server_instance_type\ninvalid or empty: aws chef_server_lb_certificate_arn\ninvalid or empty: aws opensearch_server_instance_type\ninvalid or empty: aws postgresql_server_instance_type\nempty value: aws opensearch_ebs_volume_iops\nempty value: aws opensearch_ebs_volume_size\ninvalid or empty: aws opensearch_ebs_volume_type\nempty value: aws postgresql_ebs_volume_iops\nempty value: aws postgresql_ebs_volume_size\ninvalid or empty: aws postgresql_ebs_volume_type\ninvalid or empty URL: automate fqdn\nempty value: automate instance_count\nempty value: chef server instance_count\nempty value: opensearch instance_count\nempty value: postgresql instance_count"),
+			err:     errors.New("invalid or empty: ssh_user\ninvalid or empty: ssh_key_file\ninvalid or empty s3_bucketName\ninvalid or empty: aws region\ninvalid or empty: aws aws_vpc_id\ninvalid or empty: aws private_custom_subnets\ninvalid or empty: aws public_custom_subnets\ninvalid or empty: aws ssh_key_pair_name\ninvalid or empty: aws ami_id\ninvalid or empty: aws automate_server_instance_type\ninvalid or empty: aws automate_lb_certificate_arn\nempty value: aws automate_ebs_volume_iops\nempty value: aws automate_ebs_volume_size\ninvalid or empty: aws automate_ebs_volume_type\nempty value: aws chef_ebs_volume_iops\nempty value: aws chef_ebs_volume_size\ninvalid or empty: aws chef_ebs_volume_type\ninvalid or empty: aws chef_server_instance_type\ninvalid or empty: aws chef_server_lb_certificate_arn\ninvalid or empty: aws opensearch_server_instance_type\ninvalid or empty: aws postgresql_server_instance_type\nempty value: aws opensearch_ebs_volume_iops\nempty value: aws opensearch_ebs_volume_size\ninvalid or empty: aws opensearch_ebs_volume_type\nempty value: aws postgresql_ebs_volume_iops\nempty value: aws postgresql_ebs_volume_size\ninvalid or empty: aws postgresql_ebs_volume_type\ninvalid or empty URL: automate fqdn\nempty value: automate instance_count\nempty value: chef server instance_count\nempty value: opensearch instance_count\nempty value: postgresql instance_count"),
 		},
 		{
 			name:    "Verify AWS Managed Config",
@@ -51,13 +51,13 @@ func TestParseAndVerify(t *testing.T) {
 			name:    "Verify Aws Chef Managed Config",
 			args:    args{configFile: "./testdata/HaAwsChefManaged.toml"},
 			wantErr: true,
-			err:     errors.New("invalid value '1234567' for field 'ssh_port' port number must be between 1 and 65535\ninvalid or empty: ssh_key_file\ninvalid or empty: aws profile name\ninvalid or empty: aws region\ninvalid or empty: aws aws_vpc_id\nminimum number of aws private_custom_subnets required is 3\ninvalid or empty: aws public_custom_subnets\ninvalid or empty: aws ssh_key_pair_name\ninvalid or empty: aws ami_id\ninvalid or empty: aws automate_server_instance_type\ninvalid or empty: aws automate_lb_certificate_arn\nempty value: aws automate_ebs_volume_iops\nempty value: aws automate_ebs_volume_size\ninvalid or empty: aws automate_ebs_volume_type\nempty value: aws chef_ebs_volume_iops\nempty value: aws chef_ebs_volume_size\ninvalid or empty: aws chef_ebs_volume_type\ninvalid or empty: aws chef_server_instance_type\ninvalid or empty: aws chef_server_lb_certificate_arn\ninvalid or empty: aws opensearch_server_instance_type\ninvalid or empty: aws postgresql_server_instance_type\nempty value: aws opensearch_ebs_volume_iops\nempty value: aws opensearch_ebs_volume_size\ninvalid or empty: aws opensearch_ebs_volume_type\nempty value: aws postgresql_ebs_volume_iops\nempty value: aws postgresql_ebs_volume_size\ninvalid or empty: aws postgresql_ebs_volume_type\ninvalid or empty URL: automate fqdn\npassword is too short (must be at least 8 characters)\nempty value: automate instance_count\nautomate public_key and/or private_key are missing. Otherwise set enable_custom_certs to false\nempty value: chef server instance_count\nchefServer public_key and/or private_key are missing. Otherwise set enable_custom_certs to false\nempty value: opensearch instance_count\nopensearch root_ca and/or admin_key and/or admin_cert and/or public_key and/or private_key are missing. Otherwise set enable_custom_certs to false\nempty value: postgresql instance_count\npostgresql root_ca and/or public_key and/or private_key are missing. Otherwise set enable_custom_certs to false"),
+			err:     errors.New("invalid value '1234567' for field 'ssh_port' port number must be between 1 and 65535\ninvalid or empty: ssh_key_file\ninvalid or empty: aws region\ninvalid or empty: aws aws_vpc_id\nminimum number of aws private_custom_subnets required is 3\ninvalid or empty: aws public_custom_subnets\ninvalid or empty: aws ssh_key_pair_name\ninvalid or empty: aws ami_id\ninvalid or empty: aws automate_server_instance_type\ninvalid or empty: aws automate_lb_certificate_arn\nempty value: aws automate_ebs_volume_iops\nempty value: aws automate_ebs_volume_size\ninvalid or empty: aws automate_ebs_volume_type\nempty value: aws chef_ebs_volume_iops\nempty value: aws chef_ebs_volume_size\ninvalid or empty: aws chef_ebs_volume_type\ninvalid or empty: aws chef_server_instance_type\ninvalid or empty: aws chef_server_lb_certificate_arn\ninvalid or empty: aws opensearch_server_instance_type\ninvalid or empty: aws postgresql_server_instance_type\nempty value: aws opensearch_ebs_volume_iops\nempty value: aws opensearch_ebs_volume_size\ninvalid or empty: aws opensearch_ebs_volume_type\nempty value: aws postgresql_ebs_volume_iops\nempty value: aws postgresql_ebs_volume_size\ninvalid or empty: aws postgresql_ebs_volume_type\ninvalid or empty URL: automate fqdn\npassword is too short (must be at least 8 characters)\nempty value: automate instance_count\nautomate public_key and/or private_key are missing. Otherwise set enable_custom_certs to false\nempty value: chef server instance_count\nchefServer public_key and/or private_key are missing. Otherwise set enable_custom_certs to false\nempty value: opensearch instance_count\nopensearch root_ca and/or admin_key and/or admin_cert and/or public_key and/or private_key are missing. Otherwise set enable_custom_certs to false\nempty value: postgresql instance_count\npostgresql root_ca and/or public_key and/or private_key are missing. Otherwise set enable_custom_certs to false"),
 		},
 		{
 			name:    "Verify Failed Ha Aws Managed Config",
 			args:    args{configFile: "./testdata/HaAwsManagedFailed.toml"},
 			wantErr: true,
-			err:     errors.New("invalid or empty: secrets_key_file\ninvalid or empty: secrets_store_file\ninvalid value 'awss' for field 'architecture'. Expected values are: aws, existing_nodes, deployment\ninvalid value '/hab/a3_deploy_workspace' for field 'workspace_path'. Expected values are: /hab/a2_deploy_workspace\ninvalid or empty: ssh_user\ninvalid or empty: ssh_key_file\ninvalid or empty s3_bucketName\ninvalid or empty: aws profile name\ninvalid or empty: aws region\ninvalid or empty: aws private_custom_subnets\ninvalid or empty: aws public_custom_subnets\ninvalid or empty: aws ssh_key_pair_name\ninvalid value 'aws lb_access_logs' for field 'fals'\ninvalid or empty: aws ami_id\ninvalid or empty: aws automate_server_instance_type\ninvalid or empty: aws automate_lb_certificate_arn\nempty value: aws automate_ebs_volume_iops\nempty value: aws automate_ebs_volume_size\ninvalid or empty: aws automate_ebs_volume_type\nempty value: aws chef_ebs_volume_iops\nempty value: aws chef_ebs_volume_size\ninvalid or empty: aws chef_ebs_volume_type\ninvalid or empty: aws chef_server_instance_type\ninvalid or empty: aws chef_server_lb_certificate_arn\ninvalid or empty: aws managed_opensearch_domain_name\ninvalid or empty URL: aws managed_opensearch_domain_url\ninvalid or empty: aws managed_opensearch_user_password\ninvalid or empty: aws managed_opensearch_username\ninvalid or empty: aws managed_rds_dbuser_password\ninvalid or empty: aws managed_rds_dbuser_username\ninvalid or empty URL: aws managed_rds_instance_url\ninvalid or empty: aws managed_rds_superuser_password\ninvalid or empty: aws managed_rds_superuser_username\ninvalid or empty URL: automate fqdn\nempty value: automate instance_count\nempty value: chef server instance_count"),
+			err:     errors.New("invalid or empty: secrets_key_file\ninvalid or empty: secrets_store_file\ninvalid value 'awss' for field 'architecture'. Expected values are: aws, existing_nodes, deployment\ninvalid value '/hab/a3_deploy_workspace' for field 'workspace_path'. Expected values are: /hab/a2_deploy_workspace\ninvalid or empty: ssh_user\ninvalid or empty: ssh_key_file\ninvalid or empty s3_bucketName\ninvalid or empty: aws region\ninvalid or empty: aws private_custom_subnets\ninvalid or empty: aws public_custom_subnets\ninvalid or empty: aws ssh_key_pair_name\ninvalid value 'aws lb_access_logs' for field 'fals'\ninvalid or empty: aws ami_id\ninvalid or empty: aws automate_server_instance_type\ninvalid or empty: aws automate_lb_certificate_arn\nempty value: aws automate_ebs_volume_iops\nempty value: aws automate_ebs_volume_size\ninvalid or empty: aws automate_ebs_volume_type\nempty value: aws chef_ebs_volume_iops\nempty value: aws chef_ebs_volume_size\ninvalid or empty: aws chef_ebs_volume_type\ninvalid or empty: aws chef_server_instance_type\ninvalid or empty: aws chef_server_lb_certificate_arn\ninvalid or empty: aws managed_opensearch_domain_name\ninvalid or empty URL: aws managed_opensearch_domain_url\ninvalid or empty: aws managed_opensearch_user_password\ninvalid or empty: aws managed_opensearch_username\ninvalid or empty: aws managed_rds_dbuser_password\ninvalid or empty: aws managed_rds_dbuser_username\ninvalid or empty URL: aws managed_rds_instance_url\ninvalid or empty: aws managed_rds_superuser_password\ninvalid or empty: aws managed_rds_superuser_username\ninvalid or empty URL: automate fqdn\nempty value: automate instance_count\nempty value: chef server instance_count"),
 		},
 		{
 			name:    "Verify Failed Ha On Prem Aws Managed Config",
diff --git a/lib/httputils/http_test.go b/lib/httputils/http_test.go
index 92d2b8ccd..86dae82a0 100644
--- a/lib/httputils/http_test.go
+++ b/lib/httputils/http_test.go
@@ -95,3 +95,86 @@ func TestMakeRequestConnectionError(t *testing.T) {
 	assert.Nil(t, responseBody)
 	assert.Contains(t, err.Error(), "context deadline exceeded")
 }
+
+func TestMakeRequestWithHeaderSuccessfulRequest(t *testing.T) {
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+
+		assert.Equal(t, http.MethodPost, r.Method)
+		assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
+
+		body, err := io.ReadAll(r.Body)
+		assert.NoError(t, err)
+
+		var requestBody map[string]interface{}
+		err = json.Unmarshal(body, &requestBody)
+		assert.NoError(t, err)
+
+		expectedBody := map[string]interface{}{
+			"key1": "value1",
+			"key2": "42",
+		}
+		assert.Equal(t, expectedBody, requestBody)
+
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte("Success"))
+	}))
+	defer server.Close()
+
+	logger, err := logger.NewLogger("text", "debug")
+	assert.NoError(t, err)
+	client := httputils.NewClient(logger)
+
+	url := server.URL
+	requestBody := map[string]interface{}{
+		"key1": "value1",
+		"key2": "42",
+	}
+	resp, responseBody, err := client.MakeRequestWithHeaders(http.MethodPost, url, requestBody, "Content-Type", "application/json")
+
+	assert.NoError(t, err)
+	assert.NotNil(t, resp)
+	assert.Equal(t, http.StatusOK, resp.StatusCode)
+
+	expectedResponseBody := "Success"
+	assert.Equal(t, expectedResponseBody, string(responseBody))
+}
+
+func TestMakeRequestWithHeaderConnectionError(t *testing.T) {
+	logger, err := logger.NewLogger("text", "debug")
+	assert.NoError(t, err)
+
+	client := httputils.NewClientWithTimeout(1*time.Millisecond, logger)
+
+	resp, responseBody, err := client.MakeRequestWithHeaders(http.MethodGet, "http://non-existent-server", nil, "Content-Type", "application/json")
+
+	assert.Error(t, err)
+	assert.Nil(t, resp)
+	assert.Nil(t, responseBody)
+	assert.Contains(t, err.Error(), "context deadline exceeded")
+}
+
+func TestMakeRequestWithHeaderRequestError(t *testing.T) {
+	logger, err := logger.NewLogger("text", "debug")
+	assert.NoError(t, err)
+	client := httputils.NewClient(logger)
+
+	resp, responseBody, err := client.MakeRequestWithHeaders(http.MethodGet, "invalid-url", nil, "Content-Type", "application/json")
+
+	assert.Error(t, err)
+	assert.Nil(t, resp)
+	assert.Nil(t, responseBody)
+	assert.Contains(t, err.Error(), "failed to make HTTP request")
+}
+
+func TestMakeRequestWithHeaderRequestBodyError(t *testing.T) {
+	logger, err := logger.NewLogger("text", "debug")
+	assert.NoError(t, err)
+	client := httputils.NewClient(logger)
+
+	resp, responseBody, err := client.MakeRequestWithHeaders(http.MethodPost, "https://example.com", make(chan int), "Content-Type", "application/json")
+
+	assert.Error(t, err)
+	assert.Nil(t, resp)
+	assert.Nil(t, responseBody)
+	assert.Contains(t, err.Error(), "failed to marshal request body")
+}