GrantForge

    아키텍처와 보안

    보안 설계

    세션, CSRF, 비밀번호와 잠금, 2단계 인증과 재인증, 암호화 저장, 토큰, 감사의 설계.

    콘솔 세션

    • 세션은 데이터베이스에 저장됩니다(Spring Session JDBC). 브라우저는 GRANTFORGE_SESSION 쿠키만 가지며, 이 쿠키는 HttpOnly, SameSite=Lax이고 HTTPS에서는 Secure가 붙습니다(또는 grantforge.security.cookie-secure로 강제).
    • 로그인, 2단계 인증 완료, 연합 로그인 완료 시 세션 ID와 CSRF 토큰을 교체해 세션 고정을 막습니다.
    • 상태 변경 요청은 반드시 X-XSRF-TOKEN 헤더를 보내야 하며, 값은 XSRF-TOKEN 쿠키에서 가져옵니다.
    • 관리자는 모든 세션을 조회하고 종료할 수 있습니다. 계정을 비활성화하거나 잠그거나 비밀번호를 재설정하면 그 계정의 모든 세션이 즉시 종료되고, 비밀번호를 변경하면 다른 기기의 세션이 종료됩니다.

    비밀번호

    • 새 비밀번호는 Argon2id로 해시합니다. BCrypt와 1.x에서 가져온 해시는 계속 검증할 수 있으며, 다음 로그인 시 현재 알고리즘으로 업그레이드됩니다.
    • 정책: 길이, 문자 종류, 이력, 유효 기간을 모두 설정할 수 있고, 비밀번호에 사용자 이름을 넣을 수 없습니다.
    • 연속으로 실패해 설정된 횟수에 이르면 계정을 잠급니다. 존재하지 않는 사용자 이름으로도 해시 비교를 한 번 수행해 응답 시간이 어떤 사용자 이름이 있는지 드러내지 않습니다. 비활성화된 계정과 비활성화된 테넌트는 비밀번호가 맞은 뒤에야 알려줍니다.

    2단계 인증과 재인증

    • TOTP(RFC 6238, SHA-1, 6자리, 30초, 앞뒤로 한 시간 단계씩 허용)를 사용하며, 같은 시간 단계의 인증 코드는 한 번만 쓸 수 있습니다. 1회용 복구 코드 10개는 SHA-256으로 저장합니다.
    • 2단계 인증을 켠 계정은 비밀번호가 맞으면 세션이 5분 동안 "대기" 상태로 머물고, 두 번째 단계를 완료하기 전에는 로그인한 상태가 아닙니다.
    • 민감한 인터페이스는 @RequireStepUp로 표시합니다. 2단계 인증을 켠 계정은 설정 가능한 시간 창 안에서 재인증해야 하며, 그렇지 않으면 GF-SECURITY-006가 반환되고 콘솔이 확인 창을 띄운 뒤 재시도합니다.

    암호화 저장

    신원 소스의 바인딩 비밀번호와 클라이언트 시크릿, 인증기 키, 데이터 서비스의 민감한 설정, 인가 서버의 서명 비공개 키는 모두 AES-GCM으로 암호화해 저장합니다. 키는 grantforge.security.encryption-key에서 가져오며, 설정하지 않으면 자동 생성해 데이터베이스에 저장합니다(시험 사용에만 적합). 에이전트 토큰과 OAuth 클라이언트 시크릿은 해시만 저장합니다.

    토큰

    • 인가 서버는 토큰 자체가 아니라 토큰의 해시를 저장합니다.
    • 갱신 토큰은 사용할 때마다 교체되며, 예전 토큰이 재생되면 인가 전체를 취소합니다.
    • 계정 비활성화, 잠금, 비밀번호 변경 필요, 클라이언트 비활성화, 테넌트 비활성화는 모두 토큰 갱신을 막습니다. Open API는 호출할 때마다 토큰이 여전히 유효한지 다시 확인합니다.
    • 정책 스냅샷은 Ed25519로 서명하며, 에이전트가 서명을 검증한 뒤에야 사용합니다.

    인터페이스 보호

    • 모든 인터페이스는 접근 방식을 반드시 선언해야 하며, 선언하지 않은 인터페이스는 시작할 수 없습니다. 권한이 필요한 인터페이스는 호출할 때마다 최신 스냅샷으로 검사합니다.
    • 거부된 호출은 감사에 기록됩니다(요청을 막지는 않습니다).
    • 외부 신원 소스와 이름이 같은 로컬 계정은 자동으로 연결되지 않아 계정 탈취를 막습니다.
    • CSV로 내보낼 때 =, +, -, @로 시작하는 셀에는 접두를 붙여 수식 주입을 막습니다.

    감사

    모든 관리 작업, 권한 부여 변경, 로그인 이벤트와 거부된 호출이 감사 로그에 기록됩니다. 권한 관련 변경과 그것의 감사 기록은 같은 트랜잭션에서 커밋하므로, 변경이 롤백되면 감사 기록도 남지 않습니다.

    GitHub에서 이 페이지 편집