6. API Key · CSR · 2FA · SSO · IP Allowlist

5 자격증명 평면의 영속화

API Key

  • API user 당 1개 — "Each API user has an associated API key."
  • Console API users list 에서 hover 로 복사 ("API User (ID)" 열)
  • Rename 시 API key 불변
  • Delete 시 즉시 invalid → 서드파티 통합 중단, in-flight tx 실패, 새 서명 거부
  • IP allowlist 없으면 도난된 API key 가 인터넷 임의 머신에서 사용 가능
CREATE TABLE api_keys (
  id                BINARY(16) PRIMARY KEY,
  api_user_id       BINARY(16) NOT NULL UNIQUE,
  csr_id            BINARY(16) NOT NULL,
  created_by_owner_user_id BINARY(16) NOT NULL,
  created_at        DATETIME(6) NOT NULL,
  invalidated_at    DATETIME(6),                       -- delete 시 set, immediate
  KEY (invalidated_at)
);

CSR (Certificate Signing Request)

  • RSA 4096 X.509
  • Customer-side 에서 생성 — fireblocks_secret.key 로컬 보관
  • Sandbox: 브라우저에서 자동 생성 (private key 발급 단축)
  • Co-signer end cert chain 의 leaf
CREATE TABLE csrs (
  id                BINARY(16) PRIMARY KEY,
  subject_cn        VARCHAR(255) NOT NULL,
  public_key_pem    TEXT NOT NULL,
  fingerprint_sha256 BINARY(32) NOT NULL UNIQUE,
  signed_by_intermediate_cert_id BINARY(16) NOT NULL,
  end_cert_pem      TEXT,                              -- Core Services 가 sign 후 set
  signed_at         DATETIME(6),
  expires_at        DATETIME(6) NOT NULL,
  uploaded_at       DATETIME(6) NOT NULL
);

2FA (TOTP)

  • 모든 Console user 필수 — TOTP authenticator (Google / Microsoft / LastPass / Yubico)
  • 6-digit code, time-sensitive (시간 동기화 필요)
  • WebAuthn / FIDO2 / hardware key 지원 여부: 본 자료 미명시
  • Reset 권한: 권한표 Owner + Security Admin. 본문은 Owner only (불일치 패턴)
  • 본인 reset 불가 — Owner / Security Admin 에 요청 → Owner reset → 확인 이메일 → 재로그인하여 setup
CREATE TABLE user_2fa (
  user_id           BINARY(16) PRIMARY KEY,
  -- ★ TOTP secret 은 plaintext 저장 금지. HSM-wrapped 만.
  secret_hsm_keyref VARCHAR(128) NOT NULL,
  enrolled_at       DATETIME(6) NOT NULL,
  last_used_at      DATETIME(6),
  KEY (last_used_at)
);

CREATE TABLE twofa_reset_events (
  -- append-only
  id                BINARY(16) PRIMARY KEY,
  target_user_id    BINARY(16) NOT NULL,
  actor_user_id     BINARY(16) NOT NULL,
  reset_at          DATETIME(6) NOT NULL,
  via_support       BOOLEAN NOT NULL DEFAULT FALSE,    -- Owner 본인의 reset 은 Support
  KEY (target_user_id)
);

SSO (Auth0 → 외부 IdP)

  • email domain 기반 authorization — workspace 가입자의 domain 이 list 에 있어야 로그인 가능
  • SSO 는 login authorization 만 — workspace 내 user 추가/삭제는 별개 평면 (Owner/Admin Console)
  • Service provider: Auth0 (auth.fireblocks.io/login/callback)
  • 변경: Fireblocks Support 경유, Workspace Owner 승인 필요
IdPSelf-setup주요 입력
Google WorkspaceClient ID, Secret, domain (OAuth 2.0)
Microsoft Entra IDClient ID, Secret value (★ ID 아님), domain
Oktacustomer-metadata.xml, X.509 (SAML, firstName/lastName/email 3 attr 매핑)
OpenID ConnectIssuer URL, Client ID, domain
PingFederateServer URL, X.509 (Base64)
SAML 2.0 / 3.0metadata.xml, X.509
ADFSFireblocks Support 경유
LDAP / ADFireblocks Support 경유
CREATE TABLE sso_configs (
  id                BINARY(16) PRIMARY KEY,
  workspace_id      BINARY(16) NOT NULL UNIQUE,
  idp_type          ENUM('google', 'entra', 'okta', 'oidc',
                         'pingfederate', 'saml2', 'saml3', 'adfs', 'ldap') NOT NULL,
  callback_url      VARCHAR(255) NOT NULL,             -- auth.fireblocks.io/login/callback
  client_id         VARCHAR(255),
  client_secret_hsm_keyref VARCHAR(128),               -- HSM-wrapped, never plaintext
  metadata_xml_blob BLOB,                              -- SAML 의 경우
  configured_at     DATETIME(6) NOT NULL,
  changed_at        DATETIME(6)                        -- Support 경유 변경
);

CREATE TABLE sso_authorized_domains (
  sso_config_id     BINARY(16) NOT NULL,
  email_domain      VARCHAR(255) NOT NULL,
  PRIMARY KEY (sso_config_id, email_domain)
);

IP Allowlist

  • API user/Key 단위: per-API-user, /32 CIDR only
  • 수정 권한: Owner / Security Admin (권한표) — 본문은 "Only workspace Owners" (불일치)
  • 없으면 도난된 API key 의 인터넷 임의 사용 가능
  • workspace-level IP allowlist (Console access 용) 도 별도 존재 — Owner 만
CREATE TABLE api_user_ip_allowlists (
  id                BINARY(16) PRIMARY KEY,
  api_user_id       BINARY(16) NOT NULL,
  cidr              VARCHAR(18) NOT NULL,              -- /32 only
  added_by_user_id  BINARY(16) NOT NULL,               -- Owner or Security Admin
  added_at          DATETIME(6) NOT NULL,
  removed_at        DATETIME(6),
  KEY (api_user_id, removed_at)
);

CREATE TABLE workspace_ip_allowlists (
  id                BINARY(16) PRIMARY KEY,
  workspace_id      BINARY(16) NOT NULL,
  cidr              VARCHAR(18) NOT NULL,              -- /32 only
  added_by_owner_user_id BINARY(16) NOT NULL,
  added_at          DATETIME(6) NOT NULL,
  removed_at        DATETIME(6),
  KEY (workspace_id)
);