Conversation
* feat: actuator 의존성 추가 * feat: ci-prod 구현
📝 WalkthroughWalkthrough이 PR은 프로덕션 배포 자동화를 구현한다. CI-PROD 워크플로우가 main 브랜치의 코드를 테스트하고 ECR에 이미지를 푸시하며, CD-PROD 워크플로우가 ECS로 배포한다. 프로덕션 설정, Actuator 모니터링, 서비스 디스커버리 URI 정규화가 함께 추가된다. ChangesProduction CI/CD 파이프라인
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/ci.yml (1)
16-20:⚠️ Potential issue | 🟠 Major | ⚡ Quick winci.yml과 ci-prod.yml의 JDK 버전을 통일하세요.
현재 ci.yml은 JDK 17을, ci-prod.yml은 JDK 21을 사용합니다. 개발 환경과 프로덕션 환경에서 서로 다른 Java 버전을 사용하면 dev에서 통과한 코드가 prod에서 실패할 수 있습니다. 두 워크플로우의 JDK 버전을 일치시키거나, 의도적인 차이라면 주석으로 명시해주세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/ci.yml around lines 16 - 20, ci.yml currently sets java-version: '17' while ci-prod.yml uses '21'; make these consistent by updating the actions/setup-java@v4 step (the "Set up JDK 17" / java-version field) so both workflows use the same JDK version, or if the difference is intentional, add a clear comment near the actions/setup-java@v4 step explaining why dev and prod differ; update the java-version value and/or add the comment in both workflow files (the setup-java step) so the mismatch is resolved or documented.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/cd-prod.yml:
- Around line 82-89: The current assignment to .environment replaces the entire
environment array and wipes out any pre-existing variables; instead update the
code that assigns .environment so it merges/updates entries rather than
overwriting: locate the .environment = [...] block and change the logic to
iterate over the listed names (SPRING_PROFILES_ACTIVE, SERVER_PORT,
EUREKA_ENABLED, EUREKA_HOST, EUREKA_PORT, JWT_SECRET) and for each, update the
existing env entry with the same "name" if present or append a new entry if not,
preserving all other existing environment variables in the task definition.
- Around line 28-30: The workflow currently allows workflow_run triggers from
any successful run which causes PR-built runs to trigger CD but not push image
steps; update the top-level if condition that currently checks
"github.event_name == 'workflow_dispatch' || (github.event_name ==
'workflow_run' && github.event.workflow_run.conclusion == 'success')" to also
require the workflow_run originated from a push to main (e.g., add checks like
"github.event_name == 'workflow_dispatch' || (github.event_name ==
'workflow_run' && github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'main')") so only successful
push-to-main workflow_runs trigger the CD flow and the "Verify image exists in
ECR" step will only run when the image was actually pushed.
- Around line 77-88: The JWT_SECRET is being injected as a plaintext environment
variable into the ECS task definition; change the template to place it in the
container's secrets with valueFrom instead of in .environment. Specifically,
remove the {"name":"JWT_SECRET","value":$JWT_SECRET} entry from the .environment
array in the .containerDefinitions mapping and add a .secrets entry such as
{"name":"JWT_SECRET","valueFrom":$JWT_SECRET_ARN} (or a similarly named template
arg), update the workflow args to pass the secret ARN/SSM path (e.g., replace
--arg JWT_SECRET with --arg JWT_SECRET_ARN or add a new arg) and ensure the
value supplied comes from Secrets Manager or SSM Parameter Store via repository
secrets so the ECS task uses secrets.valueFrom rather than plaintext
environment.
In @.github/workflows/ci-prod.yml:
- Around line 41-45: The "Configure AWS credentials (OIDC)" job step is
currently unconditional and runs for pull_request events; guard it the same as
the image-push steps by adding if: github.event_name == 'push' to that step so
AWS OIDC/role-to-assume is only configured on push events; update the step that
uses aws-actions/configure-aws-credentials@v4 (the Configure AWS credentials
(OIDC) step) to include the if condition and keep role-to-assume and aws-region
inputs unchanged.
In `@build.gradle`:
- Line 41: The dependency
'org.springframework.boot:spring-boot-starter-actuator' is declared twice;
remove the duplicate declaration and keep only one entry for implementation
'org.springframework.boot:spring-boot-starter-actuator' (remove either the
occurrence at the location matching the diff showing Line 41 or the earlier
declaration at Line 25) so the build.gradle contains a single actuator
dependency entry.
In
`@src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.java`:
- Line 31: Remove `/actuator/info` from the list of publicly permitted endpoints
in SecurityConfig so only `/actuator/health` remains exposed; locate the
authorizeRequests/antMatchers(...) call (inside SecurityConfig, e.g., the
configure(HttpSecurity) method or wherever permitAll is invoked) and edit the
antMatchers/permitAll array to omit "/actuator/info", leaving other entries like
"/api/*/users/signup" and "/actuator/health" unchanged.
In `@src/main/resources/application-prod.yml`:
- Around line 29-30: The production config currently exposes detailed health
info (health.show-details: always) while SecurityConfig leaves /actuator/health
and /actuator/info public; change health.show-details in application-prod.yml
from "always" to "when-authorized" (or "never" if you prefer no details at all)
and update SecurityConfig to stop permitting anonymous access to
/actuator/health and /actuator/info (require authentication or a specific role
such as ROLE_ACTUATOR) so that detailed health payloads are only returned to
authorized callers; target the health.show-details setting and the
SecurityConfig class (the permitAll/antMatchers for /actuator/*) when making
these edits.
---
Outside diff comments:
In @.github/workflows/ci.yml:
- Around line 16-20: ci.yml currently sets java-version: '17' while ci-prod.yml
uses '21'; make these consistent by updating the actions/setup-java@v4 step (the
"Set up JDK 17" / java-version field) so both workflows use the same JDK
version, or if the difference is intentional, add a clear comment near the
actions/setup-java@v4 step explaining why dev and prod differ; update the
java-version value and/or add the comment in both workflow files (the setup-java
step) so the mismatch is resolved or documented.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: f30a9ca3-5a65-4b14-b3b9-3235bf22df03
📒 Files selected for processing (7)
.github/workflows/cd-prod.yml.github/workflows/ci-prod.yml.github/workflows/ci.ymlbuild.gradlesrc/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.javasrc/main/resources/application-prod.ymlsrc/main/resources/application.yml
| if: > | ||
| github.event_name == 'workflow_dispatch' || | ||
| (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd -type f -name "*.yml" -o -name "*.yaml" | grep -E "(workflow|github)" | head -20Repository: Miche-Let/api-gateway
Length of output: 236
🏁 Script executed:
ls -la .github/workflows/ 2>/dev/null || echo "workflows directory not found"Repository: Miche-Let/api-gateway
Length of output: 491
🏁 Script executed:
cat .github/workflows/cd-prod.ymlRepository: Miche-Let/api-gateway
Length of output: 4100
🏁 Script executed:
cat .github/workflows/ci-prod.yml 2>/dev/null || cat .github/workflows/ci.yml 2>/dev/null || fd -type f -name "*ci*" .github/workflows/Repository: Miche-Let/api-gateway
Length of output: 1571
PR 성공 후에도 배포 잡이 실행되어 이미지 검증에서 실패합니다.
CI-PROD는 pull_request와 push 이벤트 모두에서 실행되지만, 여기서는 성공 여부만 확인하므로 성공한 PR 빌드도 CD 워크플로우를 트리거합니다. 그러나 이미지 푸시는 if: github.event_name == 'push' 조건으로 push 이벤트에서만 실행되므로, PR에서 트리거된 실행은 ECR에 이미지를 푸시하지 않습니다. 이로 인해 line 52의 "Verify image exists in ECR" 단계에서 매번 실패합니다. workflow_run 트리거를 push 이벤트와 main 브랜치로 제한해야 합니다.
제안 수정
if: >
github.event_name == 'workflow_dispatch' ||
- (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
+ (github.event_name == 'workflow_run' &&
+ github.event.workflow_run.conclusion == 'success' &&
+ github.event.workflow_run.event == 'push' &&
+ github.event.workflow_run.head_branch == 'main')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if: > | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') | |
| if: > | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'workflow_run' && | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event == 'push' && | |
| github.event.workflow_run.head_branch == 'main') |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/cd-prod.yml around lines 28 - 30, The workflow currently
allows workflow_run triggers from any successful run which causes PR-built runs
to trigger CD but not push image steps; update the top-level if condition that
currently checks "github.event_name == 'workflow_dispatch' || (github.event_name
== 'workflow_run' && github.event.workflow_run.conclusion == 'success')" to also
require the workflow_run originated from a push to main (e.g., add checks like
"github.event_name == 'workflow_dispatch' || (github.event_name ==
'workflow_run' && github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'main')") so only successful
push-to-main workflow_runs trigger the CD flow and the "Verify image exists in
ECR" step will only run when the image was actually pushed.
| --arg JWT_SECRET "${{ secrets.JWT_SECRET }}" \ | ||
| ' | ||
| .containerDefinitions |= map( | ||
| if .name == $CN then | ||
| .image = $IMG | ||
| | .environment = [ | ||
| {"name":"SPRING_PROFILES_ACTIVE","value":$SPRING_PROFILES_ACTIVE}, | ||
| {"name":"SERVER_PORT","value":$SERVER_PORT}, | ||
| {"name":"EUREKA_ENABLED","value":$EUREKA_ENABLED}, | ||
| {"name":"EUREKA_HOST","value":$EUREKA_HOST}, | ||
| {"name":"EUREKA_PORT","value":$EUREKA_PORT}, | ||
| {"name":"JWT_SECRET","value":$JWT_SECRET} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, locate and examine the file
fd -type f "cd-prod.yml" .github/workflows/Repository: Miche-Let/api-gateway
Length of output: 236
🏁 Script executed:
# Once found, examine lines 77-88 and surrounding context
sed -n '70,95p' .github/workflows/cd-prod.yml | cat -nRepository: Miche-Let/api-gateway
Length of output: 1432
🏁 Script executed:
# Check if JWT_SECRET is used elsewhere in the workflow
rg "JWT_SECRET" .github/workflows/cd-prod.yml -n -B2 -A2Repository: Miche-Let/api-gateway
Length of output: 562
🏁 Script executed:
# Check the full workflow file to understand the context better
wc -l .github/workflows/cd-prod.ymlRepository: Miche-Let/api-gateway
Length of output: 99
🏁 Script executed:
# Look at the complete jq command and the task definition registration
sed -n '60,120p' .github/workflows/cd-prod.yml | cat -nRepository: Miche-Let/api-gateway
Length of output: 2881
🏁 Script executed:
# Check if there are any other references to task definitions or secrets
rg "taskDefinition|secrets|Secrets Manager|SSM Parameter" .github/workflows/cd-prod.yml -nRepository: Miche-Let/api-gateway
Length of output: 359
🏁 Script executed:
# Check if JWT_SECRET_ARN or similar variables are defined elsewhere
rg "JWT_SECRET|SECRET" .github/workflows/ -n --max-count 20Repository: Miche-Let/api-gateway
Length of output: 252
🌐 Web query:
ECS task definition secrets valueFrom best practices AWS
💡 Result:
To securely manage secrets in AWS ECS using the valueFrom parameter, follow these best practices: 1. Use Managed Services: Store sensitive data in AWS Secrets Manager or AWS Systems Manager (SSM) Parameter Store [1][2]. Both services use AWS KMS for encryption at rest [1][3]. - Use Secrets Manager for secrets requiring automatic rotation, cross-account access, or multi-Region replication [1][3]. - Use SSM Parameter Store for basic configuration data and secrets that do not require these advanced features, as it is often more cost-effective [1][3]. 2. Use the Secrets Parameter: In your ECS task definition, use the secrets container definition parameter to reference these secrets via their ARN [4][5][6]. This allows the ECS agent to inject the secret value as an environment variable at container startup [7]. 3. Implement Least Privilege IAM: Ensure your task execution role has the minimum necessary permissions to retrieve secrets from the specific Secrets Manager or SSM Parameter Store resources [4][8][2]. 4. Consider Programmatic Retrieval for Dynamic Updates: Injecting secrets as environment variables via the task definition requires a task restart to pick up changes if a secret is rotated [6][7][2]. If your application requires real-time secret updates without restarting the task, modify your application code to retrieve secrets directly from Secrets Manager or SSM Parameter Store at runtime using the AWS SDK [8][2]. 5. Mitigate Environment Variable Exposure: Environment variables can sometimes be exposed in logs or via tools like docker inspect [1]. To further enhance security: - Use IAM roles to restrict access to the task definition and the secrets themselves [1][2]. - If extreme security is required, consider having a sidecar container retrieve the secret and write it to a shared volume, or have the application read directly from the secret store at runtime to avoid environment variables entirely [1][2]. - Ensure your logging configuration does not capture or log environment variables [2]. 6. Use Hierarchical Naming: When using SSM Parameter Store, adopt a consistent naming hierarchy (e.g., /app/env/key) to simplify IAM policy management and improve organization [9].
Citations:
- 1: https://docs.aws.amazon.com/AmazonECS/latest/bestpracticesguide/security-secrets-management.html
- 2: https://repost.aws/questions/QUKmWo-l06SFei_zv2_T2KpQ/best-practices-for-managing-secrets-in-ecs-environment
- 3: https://aws.amazon.com/blogs/security/how-to-choose-the-right-aws-service-for-managing-secrets-and-configurations/
- 4: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-secret.html
- 5: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/secrets-envvar-secrets-manager.html
- 6: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/secrets-envvar-ssm-paramstore.html
- 7: https://repost.aws/knowledge-center/ecs-data-security-container-task
- 8: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/secrets-app-ssm-paramstore.html
- 9: https://dev.to/aws-builders/stop-hardcoding-use-aws-parameter-store-instead-hands-on-2hcl
🌐 Web query:
ECS environment vs secrets field security best practices
💡 Result:
In Amazon ECS, the primary security best practice for handling sensitive data is to avoid hardcoding secrets in task definitions or Dockerfiles [1][2][3]. Instead, you should use the native secrets integration provided by the ECS task definition, which allows you to reference secrets stored in AWS Secrets Manager or AWS Systems Manager Parameter Store [1][4][5]. Comparison of Approaches: 1. ECS Secrets Field (Recommended): By using the secrets parameter in your container definition, ECS automatically retrieves the secret value from Secrets Manager or Parameter Store at runtime and injects it into the container [6][7]. This method ensures that sensitive values are not stored in plain text within your task definition or version control systems [3]. 2. Environment Variables (Standard): When you use the secrets field, ECS typically exposes these values as environment variables within the container [1][6][7]. While this is the standard and supported way to inject secrets, it carries inherent risks: environment variables can sometimes be exposed through logs, error messages, or by unauthorized processes inspecting the container (e.g., via docker inspect) [1][2]. Advanced Security Best Practices: To mitigate the risks associated with environment variables, consider these more secure patterns: - Direct SDK Retrieval: For highly sensitive applications, configure your application code to use the AWS SDK to fetch secrets directly from Secrets Manager or Parameter Store at runtime [1][2]. This avoids exposing the secret as an environment variable entirely [2]. - Sidecar Pattern: Run a sidecar container that retrieves the secret and writes it to a shared, memory-backed volume (tmpfs) [1][8]. Your main application container can then read the secret from this file, ensuring the secret never exists as an environment variable and resides only in memory [1][8]. - IAM Least Privilege: Regardless of the injection method, always use an IAM task execution role with the minimum necessary permissions to access only the specific secrets required by that task [1][8][2]. - Secret Rotation: Utilize AWS Secrets Manager to enable automatic secret rotation, which limits the window of opportunity if a secret is ever compromised [1][2]. In summary, while using the ECS secrets field is significantly more secure than hardcoding values, the most robust security posture involves either direct SDK retrieval or using a sidecar pattern to keep secrets out of the environment variable space [1][8][2].
Citations:
- 1: https://docs.aws.amazon.com/AmazonECS/latest/bestpracticesguide/security-secrets-management.html
- 2: https://repost.aws/questions/QUKmWo-l06SFei_zv2_T2KpQ/best-practices-for-managing-secrets-in-ecs-environment
- 3: https://dev.to/1515_1c22035d85e1ae3d/running-a-tomcat-app-on-ecs-fargate-a-complete-step-by-step-guide-36al
- 4: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data-tutorial.html
- 5: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html
- 6: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/secrets-envvar-secrets-manager.html
- 7: https://repost.aws/knowledge-center/ecs-data-security-container-task
- 8: https://dev.to/yash_pritwani_07a77613fd6/stop-putting-credentials-in-environment-variables-secret-management-for-devops-teams-2pah
JWT_SECRET를 환경변수로 평문 저장하지 마세요.
ECS 태스크 정의 리비전에 평문으로 저장되어 ecs:DescribeTaskDefinition 권한만으로도 노출됩니다. AWS 보안 모범 사례에 따라 JWT_SECRET을 environment이 아닌 ECS secrets 필드의 valueFrom으로 Secrets Manager 또는 SSM Parameter Store를 참조하도록 변경하세요.
제안 수정
- --arg JWT_SECRET "${{ secrets.JWT_SECRET }}" \
+ --arg JWT_SECRET_ARN "${{ vars.JWT_SECRET_ARN }}" \
'
.containerDefinitions |= map(
if .name == $CN then
.image = $IMG
| .environment = [
{"name":"SPRING_PROFILES_ACTIVE","value":$SPRING_PROFILES_ACTIVE},
{"name":"SERVER_PORT","value":$SERVER_PORT},
{"name":"EUREKA_ENABLED","value":$EUREKA_ENABLED},
{"name":"EUREKA_HOST","value":$EUREKA_HOST},
- {"name":"EUREKA_PORT","value":$EUREKA_PORT},
- {"name":"JWT_SECRET","value":$JWT_SECRET}
+ {"name":"EUREKA_PORT","value":$EUREKA_PORT}
]
+ | .secrets = (
+ ((.secrets // []) | map(select(.name != "JWT_SECRET")))
+ + [{"name":"JWT_SECRET","valueFrom":$JWT_SECRET_ARN}]
+ )
else .
end
)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/cd-prod.yml around lines 77 - 88, The JWT_SECRET is being
injected as a plaintext environment variable into the ECS task definition;
change the template to place it in the container's secrets with valueFrom
instead of in .environment. Specifically, remove the
{"name":"JWT_SECRET","value":$JWT_SECRET} entry from the .environment array in
the .containerDefinitions mapping and add a .secrets entry such as
{"name":"JWT_SECRET","valueFrom":$JWT_SECRET_ARN} (or a similarly named template
arg), update the workflow args to pass the secret ARN/SSM path (e.g., replace
--arg JWT_SECRET with --arg JWT_SECRET_ARN or add a new arg) and ensure the
value supplied comes from Secrets Manager or SSM Parameter Store via repository
secrets so the ECS task uses secrets.valueFrom rather than plaintext
environment.
| | .environment = [ | ||
| {"name":"SPRING_PROFILES_ACTIVE","value":$SPRING_PROFILES_ACTIVE}, | ||
| {"name":"SERVER_PORT","value":$SERVER_PORT}, | ||
| {"name":"EUREKA_ENABLED","value":$EUREKA_ENABLED}, | ||
| {"name":"EUREKA_HOST","value":$EUREKA_HOST}, | ||
| {"name":"EUREKA_PORT","value":$EUREKA_PORT}, | ||
| {"name":"JWT_SECRET","value":$JWT_SECRET} | ||
| ] |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's locate and examine the workflow file
find . -name "cd-prod.yml" -type f 2>/dev/nullRepository: Miche-Let/api-gateway
Length of output: 97
🏁 Script executed:
# Let's check if the file exists and read the relevant section
if [ -f ".github/workflows/cd-prod.yml" ]; then
echo "=== Lines 70-100 of cd-prod.yml ==="
sed -n '70,100p' ".github/workflows/cd-prod.yml" | cat -n
else
echo "File not found, checking directory structure..."
find . -path "*workflows*" -name "*.yml" -o -name "*.yaml" | head -20
fiRepository: Miche-Let/api-gateway
Length of output: 1663
🏁 Script executed:
# Get the full content of the workflow file to understand the context better
if [ -f ".github/workflows/cd-prod.yml" ]; then
wc -l ".github/workflows/cd-prod.yml"
echo "=== Full relevant section ==="
cat -n ".github/workflows/cd-prod.yml" | sed -n '75,95p'
fiRepository: Miche-Let/api-gateway
Length of output: 1225
컨테이너 환경변수를 완전히 교체하고 있습니다.
Line 82의 .environment = [...] 할당은 기존 환경변수 배열 전체를 새로운 배열로 교체하므로, task definition에 이미 설정된 다른 런타임 환경변수가 모두 손실됩니다. 필요한 변수들만 갱신/추가하도록 merge 작업으로 변경해야 배포 시 설정 유실을 방지할 수 있습니다.
제안 수정
- | .environment = [
- {"name":"SPRING_PROFILES_ACTIVE","value":$SPRING_PROFILES_ACTIVE},
- {"name":"SERVER_PORT","value":$SERVER_PORT},
- {"name":"EUREKA_ENABLED","value":$EUREKA_ENABLED},
- {"name":"EUREKA_HOST","value":$EUREKA_HOST},
- {"name":"EUREKA_PORT","value":$EUREKA_PORT},
- {"name":"JWT_SECRET","value":$JWT_SECRET}
- ]
+ | .environment = (
+ ((.environment // []) | map({key: .name, value: .value}) | from_entries)
+ + {
+ "SPRING_PROFILES_ACTIVE": $SPRING_PROFILES_ACTIVE,
+ "SERVER_PORT": $SERVER_PORT,
+ "EUREKA_ENABLED": $EUREKA_ENABLED,
+ "EUREKA_HOST": $EUREKA_HOST,
+ "EUREKA_PORT": $EUREKA_PORT,
+ "JWT_SECRET": $JWT_SECRET
+ }
+ | to_entries
+ | map({"name": .key, "value": .value})
+ )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/cd-prod.yml around lines 82 - 89, The current assignment
to .environment replaces the entire environment array and wipes out any
pre-existing variables; instead update the code that assigns .environment so it
merges/updates entries rather than overwriting: locate the .environment = [...]
block and change the logic to iterate over the listed names
(SPRING_PROFILES_ACTIVE, SERVER_PORT, EUREKA_ENABLED, EUREKA_HOST, EUREKA_PORT,
JWT_SECRET) and for each, update the existing env entry with the same "name" if
present or append a new entry if not, preserving all other existing environment
variables in the task definition.
| - name: Configure AWS credentials (OIDC) | ||
| uses: aws-actions/configure-aws-credentials@v4 | ||
| with: | ||
| role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | ||
| aws-region: ${{ vars.AWS_REGION }} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n .github/workflows/ci-prod.ymlRepository: Miche-Let/api-gateway
Length of output: 1984
PR 검증에서도 AWS 인증을 시도합니다.
Line 41-45의 Configure AWS credentials (OIDC) 단계는 if 조건이 없어서 pull_request에서도 실행됩니다. 하지만 이미지 푸시 관련 모든 단계(line 48, 52, 57)는 if: github.event_name == 'push'로 보호되어 있으므로, AWS 인증도 동일하게 보호해야 합니다. 현재 상태에서는 PR 검증 시 불필요하게 프로덕션 AWS role/OIDC에 접근하려 시도하며, PR 컨텍스트에서 권한이 없으면 실패할 수 있습니다.
제안 수정
- name: Configure AWS credentials (OIDC)
+ if: github.event_name == 'push'
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION }}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Configure AWS credentials (OIDC) | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | |
| aws-region: ${{ vars.AWS_REGION }} | |
| - name: Configure AWS credentials (OIDC) | |
| if: github.event_name == 'push' | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | |
| aws-region: ${{ vars.AWS_REGION }} |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/ci-prod.yml around lines 41 - 45, The "Configure AWS
credentials (OIDC)" job step is currently unconditional and runs for
pull_request events; guard it the same as the image-push steps by adding if:
github.event_name == 'push' to that step so AWS OIDC/role-to-assume is only
configured on push events; update the step that uses
aws-actions/configure-aws-credentials@v4 (the Configure AWS credentials (OIDC)
step) to include the if condition and keep role-to-assume and aws-region inputs
unchanged.
| testImplementation 'org.springframework.security:spring-security-test' | ||
| testRuntimeOnly 'org.junit.platform:junit-platform-launcher' | ||
|
|
||
| implementation 'org.springframework.boot:spring-boot-starter-actuator' |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify duplicate actuator declarations in Gradle dependencies
rg -n "spring-boot-starter-actuator" build.gradleRepository: Miche-Let/api-gateway
Length of output: 215
spring-boot-starter-actuator 의존성이 중복 선언되어 있습니다.
Line 41은 Line 25와 동일한 의존성이므로 중복입니다. 하나만 유지하세요.
🔧 제안 수정
- implementation 'org.springframework.boot:spring-boot-starter-actuator'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| implementation 'org.springframework.boot:spring-boot-starter-actuator' |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@build.gradle` at line 41, The dependency
'org.springframework.boot:spring-boot-starter-actuator' is declared twice;
remove the duplicate declaration and keep only one entry for implementation
'org.springframework.boot:spring-boot-starter-actuator' (remove either the
occurrence at the location matching the diff showing Line 41 or the earlier
declaration at Line 25) so the build.gradle contains a single actuator
dependency entry.
| "/api/*/auth/login", | ||
| "/api/*/auth/reissue", | ||
| "/api/*/users/signup" | ||
| "/api/*/users/signup", "/actuator/health", "/actuator/info" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify where /actuator/info is publicly exposed or referenced
rg -n "/actuator/info|permitAll\\(|management\\.endpoint\\.info|endpoints\\.web\\.exposure" \
src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.java \
src/main/resources/application-prod.yml \
src/main/resources/application.ymlRepository: Miche-Let/api-gateway
Length of output: 355
🏁 Script executed:
# SecurityConfig.java 전체 내용 확인
cat -n src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.javaRepository: Miche-Let/api-gateway
Length of output: 2979
🏁 Script executed:
# 애플리케이션 설정 파일에서 actuator 관련 설정 확인
cat src/main/resources/application.yml
cat src/main/resources/application-prod.yml 2>/dev/null || echo "application-prod.yml not found"Repository: Miche-Let/api-gateway
Length of output: 2715
🏁 Script executed:
# actuator 엔드포인트 관련 다른 참조 확인
rg -n "actuator" src/main/Repository: Miche-Let/api-gateway
Length of output: 237
/actuator/info는 공개 허용 대상에서 제외하는 것이 안전합니다.
Line 31에서 /actuator/info까지 permitAll로 열려 있습니다. 프로덕션 헬스체크 목적이면 /actuator/health만 공개하는 편이 안전합니다. /actuator/info는 애플리케이션 이름, 버전, 빌드 정보 등 메타데이터를 노출하므로 제거하여 정보 공개 최소화 원칙을 따르는 것이 권장됩니다.
🔧 제안 수정
- "/api/*/users/signup", "/actuator/health", "/actuator/info"
+ "/api/*/users/signup", "/actuator/health"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.java`
at line 31, Remove `/actuator/info` from the list of publicly permitted
endpoints in SecurityConfig so only `/actuator/health` remains exposed; locate
the authorizeRequests/antMatchers(...) call (inside SecurityConfig, e.g., the
configure(HttpSecurity) method or wherever permitAll is invoked) and edit the
antMatchers/permitAll array to omit "/actuator/info", leaving other entries like
"/api/*/users/signup" and "/actuator/health" unchanged.
| health: | ||
| show-details: always |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify risky combination across prod config + security config
rg -n "show-details|/actuator/health|/actuator/info" \
src/main/resources/application-prod.yml \
src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.javaRepository: Miche-Let/api-gateway
Length of output: 307
공개 헬스 엔드포인트와 show-details: always 조합은 내부 정보 노출 보안 위험을 초래합니다.
SecurityConfig에서 /actuator/health와 /actuator/info가 인증 없이 공개되어 있고, application-prod.yml의 line 30에서 show-details: always로 설정되어 있습니다. 이 조합은 인증되지 않은 사용자가 애플리케이션의 상세한 내부 상태 정보(데이터베이스, 디스크, 캐시 등)에 접근할 수 있게 하므로 운영 환경에서 즉시 수정이 필요합니다.
🔧 제안 수정
management:
endpoint:
health:
- show-details: always
+ show-details: when-authorized📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| health: | |
| show-details: always | |
| health: | |
| show-details: when-authorized |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/resources/application-prod.yml` around lines 29 - 30, The production
config currently exposes detailed health info (health.show-details: always)
while SecurityConfig leaves /actuator/health and /actuator/info public; change
health.show-details in application-prod.yml from "always" to "when-authorized"
(or "never" if you prefer no details at all) and update SecurityConfig to stop
permitting anonymous access to /actuator/health and /actuator/info (require
authentication or a specific role such as ROLE_ACTUATOR) so that detailed health
payloads are only returned to authorized callers; target the health.show-details
setting and the SecurityConfig class (the permitAll/antMatchers for /actuator/*)
when making these edits.
📝 작업 내용
🚀 주요 변경 사항
Summary by CodeRabbit
릴리스 노트
새로운 기능
Chores