-
Notifications
You must be signed in to change notification settings - Fork 0
chore/38 - ci 설정 #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore/38 - ci 설정 #39
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| name: CI-PROD | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: [ main, dev ] | ||
| push: | ||
| branches: [ main, dev ] | ||
|
|
||
| permissions: | ||
| contents: read # 내 코드를 읽을 수 있게(코드이동) 접근 권한을 준다. | ||
| id-token: write # OIDC 토큰을 발급할 수 있게 한다. | ||
|
|
||
| jobs: | ||
| build: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout # 내 코드 이동 깃허브 컴퓨터로 | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up JDK 17 # jdk 환경 설치 | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| distribution: temurin | ||
| java-version: "17" | ||
|
|
||
| - name: Set up Gradle | ||
| uses: gradle/actions/setup-gradle@v4 | ||
|
|
||
| - name: Grant execute permission for gradlew | ||
| run: chmod +x ./gradlew | ||
|
|
||
| - name: Run tests # 테스트 실행 | ||
| run: ./gradlew test --no-daemon | ||
|
|
||
| - name: Generate image tag | ||
| run: echo "IMAGE_TAG=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_ENV | ||
|
|
||
| - name: Configure AWS credentials (OIDC) # 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 }} | ||
|
|
||
| - name: Login to Amazon ECR # 위에서 자격증명하고 ecr 로그인 | ||
| if: github.event_name == 'push' | ||
| uses: aws-actions/amazon-ecr-login@v2 | ||
|
|
||
| - name: Build Docker image # 이미지 빌드해서 | ||
| run: | | ||
| docker build --build-arg SERVER_PORT=${{ vars.SERVER_PORT }} -t ${{ vars.ECR_REGISTRY }}/${{ vars.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }} . | ||
|
|
||
| - name: Push Docker image to ECR # 이미지 ecr로 업로드 | ||
| if: github.event_name == 'push' | ||
| run: | | ||
| docker push ${{ vars.ECR_REGISTRY }}/${{ vars.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,20 @@ | ||
| FROM eclipse-temurin:17-jre | ||
| FROM eclipse-temurin:17-jdk AS builder | ||
| WORKDIR /app | ||
|
|
||
| # 1. non-root 전용 유저 및 그룹 생성 (appuser) | ||
| RUN groupadd -r appuser && useradd -r -g appuser appuser | ||
| COPY gradlew . | ||
| COPY gradle gradle | ||
| COPY build.gradle settings.gradle ./ | ||
| COPY src src | ||
|
|
||
| RUN chmod +x ./gradlew | ||
| RUN ./gradlew bootJar -x test -x asciidoctor --no-daemon | ||
|
|
||
| # 2. 호스트(로컬 PC)에서 이미 빌드된 jar 파일을 복사 (파일 소유권 자동 지정) | ||
| COPY --chown=appuser:appuser build/libs/*-SNAPSHOT.jar app.jar | ||
| FROM eclipse-temurin:17-jre | ||
| WORKDIR /app | ||
|
|
||
| # 3. 컨테이너 실행 권한을 appuser로 전환 | ||
| USER appuser | ||
| COPY --from=builder /app/build/libs/*.jar app.jar | ||
|
|
||
| EXPOSE 19900 | ||
| ARG SERVER_PORT=19900 | ||
| EXPOSE ${SERVER_PORT} | ||
|
|
||
| ENTRYPOINT ["java", "-jar", "/app/app.jar"] | ||
|
ji-circle marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,59 @@ | ||||||||||||||
| server: | ||||||||||||||
| port: ${SERVER_PORT:19900} | ||||||||||||||
|
|
||||||||||||||
| spring: | ||||||||||||||
| application: | ||||||||||||||
| name: inventory-service | ||||||||||||||
|
|
||||||||||||||
| datasource: | ||||||||||||||
| url: jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} | ||||||||||||||
| username: ${POSTGRES_USER} | ||||||||||||||
| password: ${POSTGRES_PASSWORD} | ||||||||||||||
| driver-class-name: org.postgresql.Driver | ||||||||||||||
|
|
||||||||||||||
| data: | ||||||||||||||
| redis: | ||||||||||||||
| host: ${REDIS_HOST} | ||||||||||||||
| port: ${REDIS_PORT:6379} | ||||||||||||||
|
|
||||||||||||||
| kafka: | ||||||||||||||
| bootstrap-servers: ${KAFKA_BROKERS} | ||||||||||||||
| producer: | ||||||||||||||
| key-serializer: org.apache.kafka.common.serialization.StringSerializer | ||||||||||||||
| value-serializer: org.apache.kafka.common.serialization.StringSerializer | ||||||||||||||
| consumer: | ||||||||||||||
| key-deserializer: org.apache.kafka.common.serialization.StringDeserializer | ||||||||||||||
| value-deserializer: org.apache.kafka.common.serialization.StringDeserializer | ||||||||||||||
| group-id: ${spring.application.name}-group | ||||||||||||||
|
|
||||||||||||||
| jpa: | ||||||||||||||
| hibernate: | ||||||||||||||
| ddl-auto: update | ||||||||||||||
|
Comment on lines
+29
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # application-prod.yml 파일이 존재하는지 확인하고 내용 읽기
if [ -f "src/main/resources/application-prod.yml" ]; then
echo "=== application-prod.yml 파일 내용 ==="
cat -n "src/main/resources/application-prod.yml"
else
echo "파일을 찾을 수 없습니다."
# 유사한 파일들 찾아보기
echo "=== 유사한 설정 파일 찾기 ==="
find . -name "application*.yml" -o -name "application*.yaml" 2>/dev/null | head -20
fiRepository: Miche-Let/inventory-service Length of output: 2188 🏁 Script executed: # 프로젝트 구조 확인
echo "=== 프로젝트 구조 확인 ==="
ls -la src/main/resources/ 2>/dev/null || echo "resources 디렉토리 없음"Repository: Miche-Let/inventory-service Length of output: 550 🏁 Script executed: # 다른 환경 파일들의 ddl-auto 설정 확인
echo "=== application-docker.yml 중 ddl-auto 설정 ==="
grep -A 2 "ddl-auto" src/main/resources/application-docker.yml 2>/dev/null || echo "설정 없음"
echo -e "\n=== application-local.yml 중 ddl-auto 설정 ==="
grep -A 2 "ddl-auto" src/main/resources/application-local.yml 2>/dev/null || echo "설정 없음"
echo -e "\n=== application-perf.yml 중 ddl-auto 설정 ==="
grep -A 2 "ddl-auto" src/main/resources/application-perf.yml 2>/dev/null || echo "설정 없음"
echo -e "\n=== application.yml 중 ddl-auto 설정 ==="
grep -A 2 "ddl-auto" src/main/resources/application.yml 2>/dev/null || echo "설정 없음"Repository: Miche-Let/inventory-service Length of output: 366 🏁 Script executed: # Hibernate 프로젝트 설정에서 JPA/Hibernate 버전 확인
echo "=== Maven/Gradle 설정에서 Hibernate 버전 확인 ==="
if [ -f "pom.xml" ]; then
grep -i "hibernate\|spring-data-jpa\|spring-boot" pom.xml | head -20
elif [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then
grep -i "hibernate\|spring-data-jpa\|spring-boot" build.gradle* | head -20
fiRepository: Miche-Let/inventory-service Length of output: 795 프로덕션 환경에서 런타임에 자동으로 스키마를 변경하면 예기치 않은 드리프트와 장애가 발생할 수 있습니다. Docker 환경에서는 이미 수정 예시 jpa:
hibernate:
- ddl-auto: update
+ ddl-auto: validate📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| properties: | ||||||||||||||
| hibernate: | ||||||||||||||
| default_schema: inventory_service | ||||||||||||||
| format_sql: true | ||||||||||||||
| show-sql: true | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -name "application-prod.yml" -type fRepository: Miche-Let/inventory-service Length of output: 113 🏁 Script executed: cat -n ./src/main/resources/application-prod.ymlRepository: Miche-Let/inventory-service Length of output: 2153 🌐 Web query:
💡 Result: In production environments, you should always set spring.jpa.show-sql=false [1][2]. Enabling this property is considered a security and operational anti-pattern for several reasons [3][2][4]. Why spring.jpa.show-sql is not suitable for production: 1. Security Risk: It can inadvertently expose sensitive data, database schema details, or internal logic in your application logs [2]. 2. Performance Impact: It writes directly to standard output (System.out) without the optimizations, filtering, or asynchronous handling provided by professional logging frameworks [3][5][4]. This can cause significant performance degradation under heavy load [2]. 3. Log Noise: It generates excessive, unformatted output that fills up log files rapidly, making it difficult to identify actual application errors or security incidents [2][4]. 4. Limited Utility: It only displays the prepared statement structure (with question marks for parameters), which is often insufficient for debugging complex issues [2]. Recommended Best Practices: If you need to inspect SQL queries for troubleshooting, use the following approaches instead of show-sql: 1. Use Logging Frameworks: Configure your logging framework (e.g., Logback) to capture SQL at the appropriate level. This allows you to route logs to files, filter them, and manage them according to your organization's retention policies [5][4]. - To log SQL statements: Set logging.level.org.hibernate.SQL=DEBUG [5][6][4]. - To log parameter values: Set logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE [5][2][6][4]. 2. Use Spring Profiles: Always restrict these logging configurations to non-production profiles (e.g., dev or test) using Spring Profiles [2]. Ensure your production configuration explicitly disables them [1]. 3. Use Interceptors (Advanced): For more robust or customized logging, consider using a library like DataSource-Proxy [3][5]. This allows you to intercept JDBC calls, format them, and log them consistently without relying on Hibernate-specific properties [3][5]. Security Note: While logging SQL is a debugging tool, it is not a substitute for proper security measures. Always protect against SQL injection by using parameterized queries (which Spring Data JPA does automatically when using standard repository methods or Citations:
🌐 Web query:
💡 Result: In production environments, setting management.endpoint.health.show-details to always is generally considered a security risk and is not recommended [1][2][3]. The health endpoint is often exposed to monitoring systems (like Kubernetes liveness/readiness probes) that may not be authenticated [1][4][5]. If show-details is set to always, the endpoint may reveal sensitive internal information—such as database connection details, disk space paths, or other infrastructure-specific data—to anyone who can access the endpoint [1][3][4]. Best Practices for Production: 1. Use when-authorized: Instead of always, set management.endpoint.health.show-details to when-authorized [1][2]. This ensures that detailed health information is only visible to authenticated users with appropriate roles, while unauthenticated users (or monitoring tools) receive only the basic status [1][2]. 2. Configure Roles: When using when-authorized, you can define which roles are permitted to see the details using the management.endpoint.health.roles property [1][2]. 3. Secure Actuator Endpoints: Always protect your Actuator endpoints using Spring Security [6][7]. If you must expose the health endpoint for monitoring, ensure your security configuration explicitly permits access to the basic health status for those monitoring tools while restricting access to the detailed information [1][2][6]. 4. Limit Exposure: Only expose the endpoints you absolutely need [6][7]. Use management.endpoints.web.exposure.include to explicitly list required endpoints (e.g., health, info, prometheus) rather than using a wildcard (*) [6][4][7]. 5. Use a Separate Management Port: For enhanced security, consider running Actuator on a separate management port (management.server.port) that is not publicly accessible and can be protected by a firewall [6]. If you have secured your application and specifically require the always setting, ensure your security configuration explicitly permits access to the health endpoint for both authenticated and unauthenticated users, acknowledging the potential information disclosure [1][2]. Citations:
운영 환경의 SQL 및 헬스 엔드포인트에서 민감 정보 노출
수정 예시- show-sql: true
+ show-sql: false
@@
health:
- show-details: always
+ show-details: when-authorized🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| cloud: | ||||||||||||||
| inetutils: | ||||||||||||||
| ignored-interfaces: [ "lo", "docker.*", "veth.*" ] | ||||||||||||||
| preferred-networks: [ "10.0" ] | ||||||||||||||
| use-only-site-local-interfaces: true | ||||||||||||||
|
|
||||||||||||||
| eureka: | ||||||||||||||
| client: | ||||||||||||||
| enabled: ${EUREKA_ENABLED:false} | ||||||||||||||
| service-url: | ||||||||||||||
| defaultZone: http://${EUREKA_HOST}:${EUREKA_PORT}/eureka/ | ||||||||||||||
| instance: | ||||||||||||||
| prefer-ip-address: true | ||||||||||||||
|
|
||||||||||||||
| management: | ||||||||||||||
| endpoints: | ||||||||||||||
| web: | ||||||||||||||
| exposure: | ||||||||||||||
| include: health,info,prometheus | ||||||||||||||
| endpoint: | ||||||||||||||
| health: | ||||||||||||||
| show-details: always | ||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.