|
| 1 | +# Enhanced CLI Deploy Approval With Change Set Review |
| 2 | + |
| 3 | +* **Original Author(s):**: @stevehodgkiss, @orien |
| 4 | +* **Tracking Issue**: #370 |
| 5 | +* **API Bar Raiser**: @{BAR_RAISER_USER} |
| 6 | + |
| 7 | +This feature enhances the existing `--require-approval=any-change` option to show all stack changes (not just |
| 8 | +security changes) and integrates CloudFormation change set creation and review to provide users with an accurate |
| 9 | +preview of what will be applied before deployment execution. |
| 10 | + |
| 11 | +Modern cloud infrastructure contains critical stateful resources—databases, persistent storage, message queues, and |
| 12 | +other systems that hold valuable data and maintain complex state. Engineers deploying changes to these environments |
| 13 | +carry significant responsibility: a single misunderstood deployment can lead to data loss, service outages, or |
| 14 | +security vulnerabilities that affect customers and business operations. While Infrastructure as Code provides |
| 15 | +repeatability and version control, it doesn't eliminate the fundamental need for engineers to understand precisely |
| 16 | +what changes will be applied before execution. Tooling must bridge this gap by providing clear, accurate previews |
| 17 | +of deployment impact—especially for stateful resources where "undo" isn't always possible. This enhancement ensures |
| 18 | +that engineers have the complete information they need to make informed decisions about infrastructure changes. |
| 19 | + |
| 20 | +## Working Backwards |
| 21 | + |
| 22 | +### CHANGELOG |
| 23 | + |
| 24 | +* **feat(cli)**: enhance `--require-approval=any-change` to show all stack changes instead of only security changes |
| 25 | +* **feat(cli)**: integrate CloudFormation change set creation and display when using `--require-approval=any-change` |
| 26 | + with standard (non-hotswap) deployments |
| 27 | + |
| 28 | +The `cdk deploy --require-approval=any-change` command now shows all changes to the stack, not just security-related |
| 29 | +changes. For standard CloudFormation deployments, it creates a CloudFormation change set, displays both the template |
| 30 | +diff and the change set details, and prompts for approval before executing the change set. This provides users with |
| 31 | +the most accurate preview of what changes will actually be applied. |
| 32 | + |
| 33 | +```bash |
| 34 | +# Review all changes before deploying (enhanced behavior) |
| 35 | +cdk deploy --require-approval=any-change MyStack |
| 36 | + |
| 37 | +# Existing security-only behavior unchanged |
| 38 | +cdk deploy --require-approval=broadening MyStack |
| 39 | + |
| 40 | +# No change set review with hotswap (template diff only) |
| 41 | +cdk deploy --require-approval=any-change --hotswap MyStack |
| 42 | +``` |
| 43 | + |
| 44 | +### README |
| 45 | + |
| 46 | +#### Enhanced Change Approval |
| 47 | + |
| 48 | +The `--require-approval=any-change` option has been enhanced to provide comprehensive change review: |
| 49 | + |
| 50 | +##### Standard Deployments (without --hotswap) |
| 51 | + |
| 52 | +When using standard CloudFormation deployments, `--require-approval=any-change` now: |
| 53 | + |
| 54 | +1. **Shows All Changes**: Displays template diffs for all resource changes, not just security changes |
| 55 | +2. **Creates Change Set**: Automatically creates a CloudFormation change set for accurate deployment preview |
| 56 | +3. **Combined Display**: Shows both template diff and change set information |
| 57 | +4. **Accurate Resource Impact**: Displays physical resource changes, replacements, and dependencies |
| 58 | +5. **Requires Approval**: Prompts for confirmation before executing the change set |
| 59 | + |
| 60 | +##### Example Output |
| 61 | + |
| 62 | +``` |
| 63 | +$ cdk deploy --require-approval=any-change MyWebApp |
| 64 | +
|
| 65 | +Template Changes: |
| 66 | + [+] AWS::S3::Bucket WebAppBucket |
| 67 | + [~] AWS::Lambda::Function WebAppFunction |
| 68 | + └─ Runtime: nodejs14.x → nodejs18.x |
| 69 | + └─ MemorySize: 128 → 256 |
| 70 | + [~] AWS::IAM::Role WebAppRole |
| 71 | +
|
| 72 | +Creating change set for detailed deployment preview... |
| 73 | +Change set created: cdk-deploy-change-set-2023-12-01-143022 |
| 74 | +
|
| 75 | +CloudFormation Change Set Details: |
| 76 | +┌──────────────────────┬──────────┬─────────────────────────┬─────────────────┬─────────────────┐ |
| 77 | +│ Resource Type │ Action │ Logical ID │ Physical ID │ Replacement │ |
| 78 | +├──────────────────────┼──────────┼─────────────────────────┼─────────────────┼─────────────────┤ |
| 79 | +│ AWS::S3::Bucket │ Add │ WebAppBucket │ - │ - │ |
| 80 | +│ AWS::Lambda::Function│ Modify │ WebAppFunction │ MyWebApp-Fn123 │ False │ |
| 81 | +│ AWS::IAM::Role │ Modify │ WebAppRole │ MyWebApp-Role │ False │ |
| 82 | +└──────────────────────┴──────────┴─────────────────────────┴─────────────────┴─────────────────┘ |
| 83 | +
|
| 84 | +🔒 Security Changes: |
| 85 | + • WebAppRole: Adding permissions for s3:PutObject, s3:GetObject |
| 86 | +
|
| 87 | +📝 Parameter Changes (not visible in template): |
| 88 | + • LambdaVersion parameter updated (triggers function update) |
| 89 | +
|
| 90 | +Do you approve these changes? [y/N]: y |
| 91 | +
|
| 92 | +Executing change set... |
| 93 | +✅ Stack MyWebApp deployed successfully |
| 94 | +``` |
| 95 | + |
| 96 | +##### Hotswap Deployments |
| 97 | + |
| 98 | +When using `--require-approval=any-change` with `--hotswap`, the behavior is enhanced: |
| 99 | + |
| 100 | +- Shows template diff for all changes (previously only showed security changes) |
| 101 | +- No change set creation (hotswap bypasses CloudFormation) |
| 102 | +- Proceeds with hotswap deployment after approval |
| 103 | + |
| 104 | +##### Existing Options Unchanged |
| 105 | + |
| 106 | +- `--require-approval=never`: No approval required (default) |
| 107 | +- `--require-approval=broadening`: Only security-broadening changes require approval (unchanged behavior) |
| 108 | + |
| 109 | +--- |
| 110 | + |
| 111 | +Ticking the box below indicates that the public API of this RFC has been |
| 112 | +signed-off by the API bar raiser (the `status/api-approved` label was applied to the |
| 113 | +RFC pull request): |
| 114 | + |
| 115 | +``` |
| 116 | +[ ] Signed-off by API Bar Raiser @xxxxx |
| 117 | +``` |
| 118 | + |
| 119 | +## Public FAQ |
| 120 | + |
| 121 | +### What are we launching today? |
| 122 | + |
| 123 | +We are launching enhanced functionality for the existing `--require-approval=any-change` flag. This enhancement makes |
| 124 | +the flag show all stack changes (not just security changes) and integrates CloudFormation change set creation for |
| 125 | +standard deployments. Users get both template diff information and accurate change set details, showing exactly what |
| 126 | +CloudFormation will execute. |
| 127 | + |
| 128 | +### Why should I use this feature? |
| 129 | + |
| 130 | +The enhanced `--require-approval=any-change` addresses several use cases: |
| 131 | + |
| 132 | +1. **Complete Change Visibility**: See all changes to your stack, not just security changes |
| 133 | +2. **Accurate Deployment Preview**: Change sets show the actual changes CloudFormation will make, including parameter |
| 134 | + updates that don't appear in template diffs |
| 135 | +3. **Resource Replacement Detection**: Change sets indicate when resources will be replaced, preventing data loss |
| 136 | +4. **Production Safety**: Required approval step prevents accidental, destructive deployments |
| 137 | +5. **Compliance**: Manual review process for infrastructure changes |
| 138 | +6. **Parameter-Only Deployments**: Visibility into CloudFormation parameter changes that trigger resource updates |
| 139 | + |
| 140 | +This is particularly valuable for production environments and teams with change management requirements. |
| 141 | + |
| 142 | +## Internal FAQ |
| 143 | + |
| 144 | +### Why are we doing this? |
| 145 | + |
| 146 | +The current `--require-approval=any-change` option is misleading - it only shows security-related changes, not all |
| 147 | +changes as the name implies. This affects both standard and hotswap deployments. Users who want to review all changes |
| 148 | +before deployment don't have a good option. Additionally, template diffs don't show the complete picture of what |
| 149 | +CloudFormation will actually do: |
| 150 | + |
| 151 | +1. **Parameter Changes**: CloudFormation parameter updates that trigger resource changes don't show in template diffs |
| 152 | +2. **Resource Replacement**: Template diffs don't indicate when resources will be replaced vs. updated in-place |
| 153 | +3. **Dependency Changes**: Order of operations and dependencies are not visible in template diffs |
| 154 | +4. **Physical Resource Impact**: Template diffs show logical changes but not physical resource impacts |
| 155 | + |
| 156 | +CloudFormation change sets provide definitive information about what will actually happen during deployment. The |
| 157 | +[original implementation attempt](https://github.com/aws/aws-cdk/pull/15494) demonstrated the value of this approach. |
| 158 | + |
| 159 | +### Why should we _not_ do this? |
| 160 | + |
| 161 | +This change modifies existing behavior, which could be disruptive: |
| 162 | + |
| 163 | +1. **Behavior Change**: `--require-approval=any-change` currently only shows security changes; expanding to all changes |
| 164 | + could be unexpected |
| 165 | +2. **Performance Impact**: Creating change sets adds latency to the deployment process |
| 166 | +3. **Hotswap Incompatibility**: Change sets cannot work with hotswap deployments, creating an inconsistent user experience |
| 167 | +4. **API Dependencies**: Additional CloudFormation API calls and potential rate limiting |
| 168 | +5. **Complexity**: More code paths to maintain and test |
| 169 | + |
| 170 | +However, these concerns are mitigated by the fact that the current behavior is already misleading (the name suggests |
| 171 | +all changes, but only shows security changes), and the performance impact only affects users who explicitly opt into |
| 172 | +the approval process. |
| 173 | + |
| 174 | +### What is the technical solution (design) of this feature? |
| 175 | + |
| 176 | +The implementation enhances the existing `--require-approval` logic with change set integration: |
| 177 | + |
| 178 | +#### High-Level Flow |
| 179 | + |
| 180 | +1. **Synthesis**: Standard CDK app synthesis to generate CloudFormation templates |
| 181 | +2. **Approval Check**: Determine if approval is required based on `--require-approval` value |
| 182 | +3. **Template Diff**: Generate template diff showing all changes (enhanced from current security-only logic) |
| 183 | +4. **Deployment Type Check**: |
| 184 | + - For hotswap deployments: show template diff and proceed with existing approval flow |
| 185 | + - For standard deployments: continue to change set creation |
| 186 | +5. **Change Set Creation**: Call CloudFormation `CreateChangeSet` API |
| 187 | +6. **Combined Display**: Show both template diff and change set information |
| 188 | +7. **User Approval**: Interactive prompt for confirmation |
| 189 | +8. **Change Set Execution**: Call `ExecuteChangeSet` API on approval |
| 190 | + |
| 191 | +#### Key Components |
| 192 | + |
| 193 | +1. **Enhanced DiffAnalyzer**: Modify existing logic to detect all changes instead of only security changes |
| 194 | +2. **ChangeSetCreator**: New component to create and describe CloudFormation change sets |
| 195 | +3. **CombinedDisplayFormatter**: Format both template diff and change set information |
| 196 | +4. **ApprovalPrompt**: Enhanced to handle both template diff and change set approval |
| 197 | + |
| 198 | +#### Change Set Integration |
| 199 | + |
| 200 | +- **Automatic Creation**: Change sets are created automatically for `--require-approval=any-change` on standard |
| 201 | + deployments |
| 202 | +- **Naming Convention**: `cdk-deploy-change-set-{timestamp}` to avoid conflicts |
| 203 | +- **Cleanup**: Change sets are automatically deleted after successful execution or on cancellation |
| 204 | +- **Error Handling**: Graceful fallback to template diff only if change set creation fails |
| 205 | + |
| 206 | +### Is this a breaking change? |
| 207 | + |
| 208 | +This is technically a breaking change in behavior, but it aligns with user expectations: |
| 209 | + |
| 210 | +**Breaking aspects**: |
| 211 | + |
| 212 | +- `--require-approval=any-change` will now show all changes instead of only security changes (affects both standard and hotswap deployments) |
| 213 | +- Additional latency due to change set creation for standard deployments |
| 214 | +- Different approval prompts that include change set information for standard deployments |
| 215 | +- Hotswap deployments will show template diffs for all changes instead of only security changes |
| 216 | + |
| 217 | +**Mitigation**: |
| 218 | + |
| 219 | +- The current behavior is misleading - users expect "any-change" to mean all changes |
| 220 | +- Users explicitly opt into this behavior with the flag |
| 221 | +- Existing `--require-approval=broadening` behavior remains unchanged |
| 222 | +- Performance impact only affects users who choose to use approval |
| 223 | + |
| 224 | +**Migration path**: |
| 225 | + |
| 226 | +- Users who want the old security-only behavior should use `--require-approval=broadening` |
| 227 | +- Documentation will clearly explain the enhanced behavior |
| 228 | + |
| 229 | +### What alternative solutions did you consider? |
| 230 | + |
| 231 | +#### 1. Add New `--require-approval=all-changes` Option |
| 232 | + |
| 233 | +Add a new option value instead of changing existing behavior. |
| 234 | +**Rejected**: Would leave the misleading `any-change` option unchanged and create confusion between `any-change` and |
| 235 | +`all-changes`. |
| 236 | + |
| 237 | +#### 2. Create Separate `--review-changeset` Flag |
| 238 | + |
| 239 | +Add a separate flag specifically for change set review. |
| 240 | +**Rejected**: Creates fragmented functionality; approval and change set review are closely related concerns that should |
| 241 | +be unified. |
| 242 | + |
| 243 | +#### 3. Always Create Change Sets for Any Approval |
| 244 | + |
| 245 | +Create change sets for all `--require-approval` modes. |
| 246 | +**Rejected**: Unnecessary overhead for security-only approval workflows. |
| 247 | + |
| 248 | +#### 4. Only Show Change Sets, Remove Template Diff |
| 249 | + |
| 250 | +Show only change set information without template diff. |
| 251 | +**Rejected**: Template diffs provide valuable context about CDK-level changes that complement change set physical |
| 252 | +resource information. |
| 253 | + |
| 254 | +### What are the drawbacks of this solution? |
| 255 | + |
| 256 | +1. **Behavioral Breaking Change**: Existing `--require-approval=any-change` users will see different behavior |
| 257 | +2. **Performance Impact**: Change set creation adds 5-15 seconds to the deployment process |
| 258 | +3. **Inconsistent Experience**: Different behavior between hotswap and standard deployments |
| 259 | +4. **Additional API Calls**: More CloudFormation API usage and potential throttling |
| 260 | +5. **Complexity**: More code paths and error handling scenarios |
| 261 | +6. **User Confusion**: Users may not understand why some deployments show change sets and others don't |
| 262 | + |
| 263 | +### What is the high-level project plan? |
| 264 | + |
| 265 | +#### Phase 1: Core Implementation |
| 266 | + |
| 267 | +- Modify existing `--require-approval=any-change` logic to show all changes instead of security-only |
| 268 | +- Implement change set creation for standard (non-hotswap) deployments |
| 269 | +- Add combined display of template diff and change set information |
| 270 | +- Update approval prompt to handle change set confirmation |
| 271 | + |
| 272 | +#### Phase 2: Polish & Integration |
| 273 | + |
| 274 | +- Implement change set cleanup on success/failure |
| 275 | +- Add comprehensive error handling for change set creation failures |
| 276 | +- Optimize display formatting for large change sets |
| 277 | +- Add a configuration option in `cdk.json` for change set timeout |
| 278 | + |
| 279 | +#### Phase 3: Documentation & Migration |
| 280 | + |
| 281 | +- Update CLI help text and documentation |
| 282 | +- Create a migration guide for users affected by the behavior change |
| 283 | +- Add examples and best practices |
| 284 | +- Performance optimization based on usage patterns |
| 285 | + |
| 286 | +### Are there any open issues that need to be addressed later? |
| 287 | + |
| 288 | +1. **User Communication**: How to best communicate the behavior change to existing users |
| 289 | +2. **Change Set Cleanup**: Automatic cleanup strategy for failed or cancelled deployments |
| 290 | +3. **Large Change Sets**: Optimal display format for deployments with hundreds of resources |
| 291 | +4. **Nested Stacks**: Change set behavior with nested stack deployments |
| 292 | +5. **Performance Optimization**: Caching strategies to reduce change set creation time |
| 293 | +6. **Error Recovery**: Fallback strategies when change set creation fails |
| 294 | +7. **Configuration**: Options to disable change set creation for specific environments |
| 295 | + |
| 296 | +## Appendix |
| 297 | + |
| 298 | +### CloudFormation Change Set API Reference |
| 299 | + |
| 300 | +- [`CreateChangeSet`](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateChangeSet.html): |
| 301 | + Create change set for deployment preview |
| 302 | +- [`DescribeChangeSet`](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeChangeSet.html): |
| 303 | + Get detailed change set information |
| 304 | +- [`ExecuteChangeSet`](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ExecuteChangeSet.html): |
| 305 | + Execute approved changes |
| 306 | +- [`DeleteChangeSet`](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DeleteChangeSet.html): |
| 307 | + Clean up change sets after execution or cancellation |
| 308 | + |
| 309 | +### Current vs Enhanced Behavior |
| 310 | + |
| 311 | +| Scenario | Current Behavior | Enhanced Behavior | |
| 312 | +|----------|------------------|-------------------| |
| 313 | +| `--require-approval=any-change` (standard deploy) | Shows only security changes, direct deploy | Shows all changes + change set, execute change set | |
| 314 | +| `--require-approval=any-change` (hotswap) | Shows only security changes, hotswap deploy | Shows all changes, hotswap deploy | |
| 315 | +| `--require-approval=broadening` | Shows security changes, direct deploy | **Unchanged** | |
| 316 | +| `--require-approval=never` | No approval, direct deploy | **Unchanged** | |
| 317 | + |
| 318 | +### Hotswap Compatibility |
| 319 | + |
| 320 | +Hotswap deployments bypass CloudFormation entirely, making them incompatible with change sets: |
| 321 | + |
| 322 | +- **With hotswap**: Template diff shows all changes, approval prompt, then hotswap deployment (no change set) |
| 323 | +- **Without hotswap**: Template diff + change set details, approval prompt, then change set execution |
| 324 | + |
| 325 | +### Migration Guide |
| 326 | + |
| 327 | +**For users currently using `--require-approval=any-change`:** |
| 328 | + |
| 329 | +**Before (current behavior):** |
| 330 | + |
| 331 | +- Only security-related changes shown in template diff |
| 332 | +- Direct CloudFormation deployment (standard) or hotswap deployment |
| 333 | +- Fast deployment after approval |
| 334 | + |
| 335 | +**After (enhanced behavior):** |
| 336 | + |
| 337 | +- All changes shown in template diff (security + non-security) |
| 338 | +- **Standard deployments**: Change set creation and review + template diff |
| 339 | +- **Hotswap deployments**: Enhanced template diff showing all changes (no change set) |
| 340 | +- Slightly slower for standard deployments due to change set creation |
| 341 | +- More accurate preview of deployment impact |
| 342 | + |
| 343 | +**If you want the old behavior:** |
| 344 | +Use `--require-approval=broadening` which maintains the current security-only focus. |
| 345 | + |
| 346 | +### Example Scenarios |
| 347 | + |
| 348 | +#### Scenario 1: Lambda Function Update |
| 349 | + |
| 350 | +```bash |
| 351 | +# Template shows: Lambda function code change |
| 352 | +# Change set shows: UpdateFunctionCode API call, no replacement |
| 353 | +# User sees: Both perspectives for complete understanding |
| 354 | +``` |
| 355 | + |
| 356 | +#### Scenario 2: RDS Parameter Change |
| 357 | + |
| 358 | +```bash |
| 359 | +# Template shows: No visible changes (parameter-only update) |
| 360 | +# Change set shows: Database replacement required due to parameter change, ALL DATA WILL BE LOST |
| 361 | +# User sees: Critical information that template diff cannot provide |
| 362 | +``` |
| 363 | + |
| 364 | +#### Scenario 3: Security Group Modification |
| 365 | + |
| 366 | +```bash |
| 367 | +# Template shows: Security group rule changes |
| 368 | +# Change set shows: Which EC2 instances will be affected by the change |
| 369 | +# User sees: Both logical and physical impact of the change |
| 370 | +``` |
0 commit comments