Repository navigation
fix: CSP role API symmetry & registry sync fixes, CSP validation remediation guidance, security - #90
Merged
Merged
Conversation
chore: remove legacy project-by-id actions from unused mcmp_api.yaml asset
fix: UpdateCspRole이 IdpIdentifier 등 4필드를 반영하도록 수정
updateCspRole이 PUT /api/roles/csp-roles/id/{roleId}를 가리켰으나
해당 PUT 라우트가 등록되어 있지 않았음. 실제 CSP Role 레코드 수정
핸들러(UpdateCspRoleRecord)가 등록된 경로 /api/roles/csp/id/{roleId}로
수정. 세 레지스트리 파일 모두 동일하게 반영.
fix: mcmp API 레지스트리 updateCspRole 액션이 미등록 라우트를 가리키던 문제 수정
CspValidationService의 각 ValidationStep에 실패 시 첨부할 구조화된 설정 방안(RemediationGuide: Summary/ConsoleSteps/Template/DocsRef) 필드를 추가. stepRunner가 remediation을 받아 실패 시 자동 첨부하도록 시그니처 변경. 기존 22개 호출부는 전부 nil로 갱신(동작 변화 없음) — AWS/GCP별 실제 remediation 콘텐츠는 후속 브랜치에서 채운다.
AWS OIDC/SAML/SECRET_KEY 검증 실패 단계에 CSP 콘솔 조치 방법을 담은 RemediationGuide를 첨부한다. AWS/Keycloak 리소스를 확인하는 단계 (OIDC/SAML Provider, IAM Role Trust Policy, Keycloak 클라이언트 설정, Access Key 등)에는 콘솔 경로와 Trust Policy 템플릿을 제공하고, DB 내부 조회 단계(매핑 조회, CspRole 설정)는 CSP 콘솔 조치가 없으므로 그대로 nil 유지.
… CSP validation GCP OIDC 검증(validateGCPWithOIDC) step 4/5가 문자열만 반환하던 placeholder였던 문제(OI-17)를 해결. GcpCredentialService에 ExchangeToken/GenerateAccessToken을 독립 메서드로 노출하여 STS 토큰 교환과 SA Impersonation을 각각 검증하고, 실패 시 CSP 콘솔에서의 조치 방법(RemediationGuide)을 함께 반환하도록 확장. - ExchangeTokenAndImpersonate는 두 신규 메서드를 내부에서 호출하도록 리팩터링 (기존 호출부인 csp_credential_service.go의 동작/시그니처는 변경 없음) - step 4(GCP STS 토큰 교환), step 5(SA Impersonation) 실패 시 WIF Pool/Provider, Service Account 설정 방법을 안내하는 RemediationGuide 첨부 - GCP STS/IAM Credentials 엔드포인트를 테스트에서 오버라이드 가능한 패키지 변수로 분리하여 단위 테스트 추가
validateGCPWithOIDC의 Step 3/4도 credential-issuance 경로와 동일하게 Access Token을 GCP WIF STS에 전달하고 있었다. ID Token으로 수정.
… in remediation text CspRole.idp_identifier가 GCP WIF STS audience로 그대로 전달되므로 //iam.googleapis.com/ 접두사가 필요하다는 점과, attributeCondition을 in 대신 등가 비교로 쓰는 것을 권장하는 안내를 gcpStsRemediation에 추가. 실 GCP 계정 검증 중 발견한 두 함정을 반영.
…remediation 실제 mcmp-admin/mcmp-operator SA로 WIF impersonation을 구성하며 roles/iam.workloadIdentityUser만으로는 토큰 발급(generateAccessToken)이 403(iam.serviceAccounts.getAccessToken denied)으로 실패함을 확인. roles/iam.serviceAccountTokenCreator를 함께 부여해야 한다는 점을 gcpSaImpersonationRemediation 안내에 반영.
feat: add remediation guidance to CSP validation
레지스트리 YAML을 고쳐도 서비스의 _meta(version/generatedAt)를 갱신하지 않으면 syncServicesAndActions가 해당 서비스 액션 전체를 조용히 스킵한다 (shouldUpdateService). IAM-TECH-020의 updateCspRole 경로 수정이 배포+ 수동 동기화 후에도 반영되지 않았던 원인. mc-iam-manager 서비스의 generatedAt을 갱신해 실제로 재동기화되도록 수정. shouldUpdateService 단위테스트 3건 추가(동일 메타 스킵/generatedAt 변경 시 갱신/신규 서비스 항상 갱신).
레지스트리 updateCspRole 액션이 가리키던 미등록 라우트(/api/roles/csp-roles/id/{roleId})의
실체는 main.go에 등록된 적 없는 죽은 핸들러 UpdateCspRole(RoleMaster, roleType=csp)이었고,
그 swagger 주석이 registry에 잘못된 경로를 흘려보내고 있었다. 이 죽은 핸들러를 제거해
swagger 문서(docs/, src/docs/)에서도 잘못된 경로가 사라지도록 재생성했다.
CSP Role 레코드(mcmp_role_csp_roles) 수정 핸들러는 형제 액션(createCspRole/deleteCspRole/
getCspRoleById)과 이름을 맞춰 UpdateCspRoleRecord -> UpdateCspRole로 변경했다(경로는
기존과 동일 /api/roles/csp/id/{roleId}).
한편 RoleMaster(플랫폼/워크스페이스/CSP 공용 역할 정의) 수정은 platform-roles/workspace-roles
namespace에 Create/Delete/Get만 있고 Update가 빠져있던 것으로 확인되어, 대칭을 맞춰
UpdatePlatformRole/UpdateWorkspaceRole을 신설했다. CSP 타입 RoleMaster 수정은
UpdateCspRoleMaster(/api/roles/csp-roles/master/id/{roleId})로 명확히 분리해
CSP Role 레코드 수정(UpdateCspRole)과 이름이 겹치지 않게 했다.
RoleMaster에는 타입이 없고 RoleSub가 타입을 가지며(다중 가능) 하므로, 세 핸들러 모두
요청 바디의 RoleTypes가 아닌 DB의 기존 RoleSub를 기준으로(GetRoleByID) roleId가 실제로
해당 타입인지 검증하도록 가드를 구현했다. 관련 단위테스트 3건 추가.
fix: mcmp API 레지스트리 동기화 버그 수정 + CSP Role 관련 API 정리
.env contained real Keycloak/DB/CSP secrets and was tracked in git despite being listed in .gitignore. Untrack it so it stops being committed going forward; the file remains on disk for local runtime config. All exposed values must be rotated separately.
콘솔 Edit 모달은 Name을 읽기 전용으로 취급해 저장 요청에 cspRoleName을 보내지 않는데, existingRole.Name = req.CspRoleName이 IdpIdentifier 등 다른 필드와 달리 빈 값 가드 없이 무조건 반영되어 저장할 때마다 Name이 빈 문자열로 초기화되고 있었다. Description도 동일 문제 확인, 같은 패턴(값 있을 때만 반영)으로 함께 수정. 단위 테스트 2건 추가(빈 이름으로 수정 시 기존 이름 보존 / 실제 이름 전달 시 정상 반영).
fix(security): stop tracking .env (IAM-BUG-009)
make()로 만든 zero-value 슬롯에 append로 덧붙이던 기존 로직이 실제로는 요청 개수의 2배 슬라이스를 만들었고, 앞쪽 절반이 RoleType="" 오염 row로 DB에 저장됐다. CreateWorkspaceRole과 동일한 인덱스 대입 패턴으로 통일.
FindRoleMasterCspRoleMappings가 auth_method='OIDC'로 고정 필터링해 SAML/SECRET_KEY로 등록된 매핑이 조회에서 항상 누락되던 문제를 옵셔널 필터(req.AuthMethod 지정 시에만 필터링)로 교체. 부수 발견: 같은 파일의 FindWorkspaceRoleCspRoleMappings에도 동일한 하드코딩이 있어 같은 패턴으로 함께 수정.
- DeleteCspRole(레코드 CRUD 네임스페이스, /roles/csp/id/:roleId)가 실제로는 RoleMaster의 RoleSub 태그만 삭제하던 이름-동작 불일치를 해소. 이제 이 경로는 실제로 CspRole(mcmp_role_csp_roles) 레코드를 삭제한다: 참조하는 RoleMasterCspRoleMapping을 먼저 정리(DeleteRoleCspRoleMappingsByCspRoleID 신규)한 뒤 레코드를 cascade 삭제(CspRolePolicyMapping/CspRolePermission 포함)하고, CspType=aws인 경우 실제 클라우드 Role도 함께 삭제한다(CreateCspRole과 대칭되는 CspType 분기). - 기존 RoleMaster/RoleSub 삭제 로직(Predefined 체크, 매핑 존재 시 차단 가드)은 신설된 DeleteCspRoleMaster(DELETE /roles/csp-roles/master/id/:roleId)로 이전 — DeletePlatformRole/DeleteWorkspaceRole과 동일한 패턴. - CreateCspRoleMaster(POST /roles/csp-roles/master) 신설 — CreatePlatformRole/ CreateWorkspaceRole과 대칭되는 csp 타입 전용 생성 API. UpdateCspRoleMaster(PR #150 머지 완료)에 이어 Create/Delete까지 platform/workspace/csp 3타입 API 대칭 완성. - 죽은 코드였던 CspRoleService/CspRoleRepository의 기존 DeleteCspRole/DeleteCSPRole (하드삭제/존재하지 않는 테이블명 JOIN/cascade 미정리/CspType 무관 AWS 하드코딩의 4중 버그)는 새 로직으로 완전히 대체. - swagger 재생성(docs/, src/docs/ 양쪽) Test plan: 단위테스트 7건 신규(레포지토리 cascade 1건, 핸들러 6건) — 전부 PASS
fix: UpdateCspRole이 빈 값 Name/Description을 무조건 덮어써 데이터 유실되는 버그 수정
…ub-bug fix(role): CreatePlatformRole RoleSub 배열 생성 버그 수정
SAML CSP 확장(IAM-FIX-004) 완료로 실제 SAML 매핑이 쓰이기 시작하면서 발견: - UpdateRole(role_handler.go)이 RoleMasterCspRoleMapping 재생성 시 req.CspRoles의 authMethod를 무시하고 항상 constants.AuthMethodOIDC로 고정 반영하고 있었음. 저장(수정) 때마다 기존 SAML/SECRET_KEY 매핑이 OIDC로 덮어써지는 문제. - CreateRole이 CSP 역할 생성 후 매핑 생성용 createdCspRoles를 재구성할 때 원본 요청의 authMethod를 복사하지 않아, SAML로 생성한 CSP 역할인데도 매핑은 항상 OIDC로 기록되던 문제. 두 곳 모두 요청에 지정된 authMethod를 그대로 전달하도록 수정(비어있으면 CreateRoleCspRoleMapping repository가 기존과 동일하게 OIDC로 기본 반영). IAM-BUG-020(FindRoleMasterCspRoleMappings 등 OIDC 하드코딩 제거) 작업 중 사용자 확인으로 함께 발견되어 같은 PR에 포함.
…pings-oidc-hardcode fix(role): CSP 역할 매핑 조회 auth_method OIDC 하드코딩 제거
fix(role): DeleteCspRole 재배선(레코드 삭제) + CSP 타입 Create/Delete API 대칭 완성
IAM-TECH-022에서 신설한 DeleteCspRoleRecord가 cascade 정리 대상으로 CspRolePermission(mcmp_csp_role_permissions)을 삭제 시도했으나, 이 모델은 main.go의 AutoMigrate 목록에 포함된 적이 없어 어떤 환경에도 테이블이 존재하지 않는다. 관련 레포지토리 메서드(AddPermissionsToCSPRole 등)도 호출부 없는 죽은 코드로 확인. 실제 원격 dev 환경에서 DELETE 호출 시 "relation does not exist" 500 에러로 항상 실패하던 것을 재현·수정. CspRolePermission 삭제 단계를 제거하고, 실제 존재하는 CspRolePolicyMapping cascade 정리는 유지. 테스트 DB 마이그레이션에서도 CspRolePermission을 제거해 향후 동일 회귀를 테스트가 잡아낼 수 있도록 함.
…t-table fix(role): DeleteCspRoleRecord api 보완
ssl_ciphers only listed RSA-suite ciphers (ECDHE-RSA-*), but the server's Let's Encrypt certificate is ECDSA. No cipher could be negotiated under TLS 1.2 for an ECDSA cert, causing handshake_failure and breaking Alibaba IMS OIDC discovery (TLS 1.3-only backends work by accident since TLS 1.3 cipher suites are cert-signature-agnostic).
fix(nginx): allow ECDSA cipher suites for TLS 1.2
IP/도메인으로 설치한 경우 3001, 9090 등 SSL 전용 포트로 평문 HTTP 요청이 들어오면 nginx가 내부적으로 497 코드를 발생시키고 400을 반환하던 문제. http 컨텍스트에 error_page 497 리다이렉트를 한 줄 추가해 모든 listen <port> ssl 서버 블록에 상속되도록 처리.
ListUserWorkspaces는 platformAdmin이면 멤버십 검사를 건너뛰고 전체 workspace/project를 반환하지만, ListUserProjectsByWorkspace는 같은 우회 분기가 없어 mcmp_user_workspace_roles 매핑이 없으면 platformAdmin도 403을 받았다. 두 API가 동일한 platformAdmin 우회 패턴을 쓰도록 맞춘다.
1_setup_auto.sh에 Step 8-1을 추가해, 워크스페이스-프로젝트 매핑 이후 platformAdmin 계정에 기본 workspace의 workspace role(PREDEFINED_ROLE 첫 항목)을 할당한다. platformAdmin이라도 mcmp_user_workspace_roles 매핑이 없는 상태 자체를 줄이는 보완 조치이며, 실패해도 non-fatal로 처리해 클린 설치 전체를 막지 않는다.
…ject-scope fix(user): platformAdmin의 workspace project 목록 조회 403 수정
fix(nginx): SSL 전용 포트에 평문 HTTP 요청 시 HTTPS로 리다이렉트
…per로 통일 IAM-BUG-022(#159) 수정에서 새로 넣은 platformAdmin 판별 루프가 이미 같은 파일에 있던 checkRoleFromContext와 중복이었다. 이런 중복이 바로 IAM-BUG-022 자체의 원인(ListUserWorkspaces에만 있던 우회 분기가 ListUserProjectsByWorkspace에 이식되지 않음)이었으므로, 기존 checkRoleFromContext(c, []string{"platformAdmin"})를 재사용하도록 정리해 같은 클래스의 버그가 재발할 여지를 줄인다. 또한 1_setup_auto.sh의 platformAdmin 기본 workspace role 할당이 PREDEFINED_ROLE 첫 항목을 암묵적으로 admin급으로 가정하던 부분에, 운영자가 순서를 바꾼 환경을 위해 MC_IAM_MANAGER_PLATFORMADMIN_WORKSPACE_ROLE 오버라이드를 추가한다.
refactor(user): I코드 리뷰 후속 정리
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Added
UpdatePlatformRole,UpdateWorkspaceRole,UpdateCspRoleMaster— RoleMaster update was previously missing entirely (create/delete-only) (#150)CreateCspRoleMaster/DeleteCspRoleMaster— CSP-type RoleMaster create/delete, completing platform/workspace/csp symmetry (#155)MC_IAM_MANAGER_PLATFORMADMIN_WORKSPACE_ROLEenv var to explicitly pick the workspace role assigned to platformAdmin during clean install, instead of silently assumingPREDEFINED_ROLE's first entry (#160)Fixed
updateCspRolemcmp API registry action pointed at an unregistered route; corrected across all three registry files (#148)_meta.generatedAtinvalidation that preventedsyncServicesAndActionsfrom picking up registry YAML edits (#150)UpdateCspRole(RoleMaster)handler whose stale swagger comment was the source of the broken registry path above; renamed the real CSP-role-record update handler toUpdateCspRolefor naming symmetry withcreateCspRole/deleteCspRole/getCspRoleById(#150)UpdateCspRolewas overwritingName/Descriptionwith empty strings whenever the console (which treats Name as read-only) omitted them — fixed to only apply non-empty values, matching the existing guard on other fields (#151)UpdateCspRolenow also reflectsIdpIdentifier/IamIdentifier/IamRoleId/Path(#147)CreatePlatformRolebuilt a RoleSub slice viaappendon top of a pre-sizedmake(), doubling the slice and writing half the rows with an emptyRoleType; switched to indexed assignment matchingCreateWorkspaceRole(#153)FindRoleMasterCspRoleMappings/FindWorkspaceRoleCspRoleMappingshardcodedauth_method='OIDC', so SAML/SECRET_KEY-registered mappings never showed up in lookups; filter is now optional (#154)CreateRole/UpdateRolealways wrote CSP role mappings withauthMethod=OIDCregardless of the request, silently converting SAML/SECRET_KEY mappings back to OIDC on every edit (#154)DeleteCspRole(/roles/csp/id/:roleId) actually only removed the RoleMaster's RoleSub tag despite its name; it now deletes the real CSP role record (mapping cleanup, cascade, and cloud-side role deletion for AWS), matchingCreateCspRole. The old RoleMaster delete/guard logic moved to the newDeleteCspRoleMaster(#155)DeleteCspRoleRecordcascade tried to delete fromCspRolePermission, a model never included inAutoMigrate— the table doesn't exist in any environment, so every delete failed with a 500. Removed the dead cleanup step (#156)ssl_ciphersonly listed RSA-suite ciphers; an ECDSA (Let's Encrypt) certificate couldn't negotiate under TLS 1.2, breaking Alibaba IMS OIDC discovery. Added ECDSA suites (#157)error_page 497redirect to HTTPS at thehttpcontext so it applies to everylisten <port> sslserver block (#158)ListUserProjectsByWorkspacereturned 403 for platformAdmin whenever the caller had nomcmp_user_workspace_rolesmapping (e.g. right after a clean install), because it lacked the platformAdmin bypass thatListUserWorkspacesalready had — added the same bypass, plus an optional clean-install step to assign platformAdmin a default workspace role (#159, #160)mcmp_api.yamlasset (#146)Migration notes
updateCspRoleregistry path fix requires a registry re-sync — now works correctly thanks to the_meta.generatedAtfix included in this range