<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>신뢰 on J2eff's Garage</title><link>https://blog.j2eff.me/tags/%EC%8B%A0%EB%A2%B0/</link><description>Recent content in 신뢰 on J2eff's Garage</description><generator>Hugo -- gohugo.io</generator><language>ko-KR</language><lastBuildDate>Mon, 06 Jul 2026 11:00:00 +0900</lastBuildDate><atom:link href="https://blog.j2eff.me/tags/%EC%8B%A0%EB%A2%B0/index.xml" rel="self" type="application/rss+xml"/><item><title>맨 아래 거북이 — 제네시스 계정과 신뢰의 뿌리</title><link>https://blog.j2eff.me/p/%EB%A7%A8-%EC%95%84%EB%9E%98-%EA%B1%B0%EB%B6%81%EC%9D%B4-%EC%A0%9C%EB%84%A4%EC%8B%9C%EC%8A%A4-%EA%B3%84%EC%A0%95%EA%B3%BC-%EC%8B%A0%EB%A2%B0%EC%9D%98-%EB%BF%8C%EB%A6%AC/</link><pubDate>Mon, 06 Jul 2026 11:00:00 +0900</pubDate><guid>https://blog.j2eff.me/p/%EB%A7%A8-%EC%95%84%EB%9E%98-%EA%B1%B0%EB%B6%81%EC%9D%B4-%EC%A0%9C%EB%84%A4%EC%8B%9C%EC%8A%A4-%EA%B3%84%EC%A0%95%EA%B3%BC-%EC%8B%A0%EB%A2%B0%EC%9D%98-%EB%BF%8C%EB%A6%AC/</guid><description>&lt;!--
제목 후보 (Jeff 선택용):
 1. 맨 아래 거북이 — 제네시스 계정과 신뢰의 뿌리 ← 현재 가안
 2. 최초의 루트는 누가 만드나
 3. 신뢰는 어디서 끝나는가
--&gt;
&lt;p&gt;6편에서 슬쩍 넘어간 게 있다. &amp;ldquo;씨앗 계정&amp;quot;이라 부르며 &amp;ldquo;하드코딩된 특별한 존재&amp;quot;라고만 하고 지나갔다. 이번 편은 그 씨앗의 정체를 밝히고, 거기서 시작된 질문을 끝까지 따라간다. &lt;strong&gt;최초의 루트는 대체 누가 만드는가?&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="씨앗의-진짜-이름"&gt;씨앗의 진짜 이름
&lt;/h2&gt;&lt;p&gt;씨앗은 아무 계정이 아니었다. 그건 &lt;strong&gt;제네시스 계정&lt;/strong&gt; — 모든 것이 거기서 파생되는 최초의 관리 계정이다. mincloud에서 그 번호를 &lt;code&gt;000000000001&lt;/code&gt;로 못박았다. 지금까지 &lt;code&gt;user/jeff&lt;/code&gt; 흉내를 내던 개발 자격증명을, 진짜 정체인 루트로 되돌린다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 제네시스 &amp;#39;관리 계정&amp;#39;과 그 루트를 심는다 — 어떤 서명된 요청보다도&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 먼저 존재해야 하는 단 하나의 계정. AWS 가입 순간 루트가 존재하는 것과 같다.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;loadManagementRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;credstore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;MINCLOUD_MANAGEMENT_ACCOUNT_ID&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;000000000001&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accessKeyID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;credstore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Credential&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;SecretAccessKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;credstore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;			&lt;/span&gt;&lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;			&lt;/span&gt;&lt;span class="nx"&gt;UserID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 루트의 UserId는 계정 ID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;			&lt;/span&gt;&lt;span class="nx"&gt;ARN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;arn:aws:iam::&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;:root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;accessKeyID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;이제 마스터 키로 신원을 물으면, 관리 계정의 루트가 돌아온다.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ aws sts get-caller-identity --endpoint-url http://localhost:9900
{
 &amp;#34;UserId&amp;#34;: &amp;#34;000000000001&amp;#34;,
 &amp;#34;Account&amp;#34;: &amp;#34;000000000001&amp;#34;,
 &amp;#34;Arn&amp;#34;: &amp;#34;arn:aws:iam::000000000001:root&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;이게 AWS의 &lt;strong&gt;관리 계정(management account)&lt;/strong&gt; 에 대응한다. 조직의 꼭대기 계정, 나머지 모든 계정이 그 아래에서 태어나는 뿌리다.&lt;/p&gt;
&lt;h2 id="그런데-그-루트는-누가-만들었나"&gt;그런데 그 루트는 누가 만들었나
&lt;/h2&gt;&lt;p&gt;여기서 6편의 순환이 한 층 더 깊어진다. 계정을 만들려면 계정이 있어야 한다고 했다. 그래서 부트스트랩은 서명 밖에 있어야 한다고. 좋다. 그런데 그 &lt;strong&gt;최초의 관리 계정 루트 자신&lt;/strong&gt;은 누가 만들었는가? 그것도 서명 밖에서 만들어져야 하는데, 그럼 그걸 만든 권한은 어디서 왔는가?&lt;/p&gt;
&lt;p&gt;무한히 위로 올라갈 것 같지만, 그렇지 않다. &lt;strong&gt;바닥은 다른 &amp;lsquo;키&amp;rsquo;가 아니다.&lt;/strong&gt; 거북이 탑은 물리적·조직적 통제에서 끝난다.&lt;/p&gt;
&lt;p&gt;mincloud의 경우, 제네시스 루트를 심는 건 &lt;code&gt;loadManagementRoot&lt;/code&gt;다. 그럼 그걸 실행할 권한은? &lt;strong&gt;바이너리를 실행할 수 있는 사람&lt;/strong&gt; — 이 박스를 통제하는 사람이다. 서명도 자격증명도 아니다. &amp;ldquo;기계에 손을 댈 수 있는가&amp;quot;가 최종 신뢰의 뿌리다.&lt;/p&gt;
&lt;p&gt;AWS도 원리는 같다. IAM·계정 시스템 자체가 AWS가 운영하는 서버 위의 소프트웨어고, 그 최초 상태는 &lt;strong&gt;API가 아니라 인프라 프로비저닝으로&lt;/strong&gt; 심긴다. 신뢰의 뿌리는 암호가 아니라 &lt;strong&gt;&amp;ldquo;데이터센터와 하드웨어를 물리적으로 소유·통제한다&amp;rdquo;&lt;/strong&gt; 는 사실이다. 소프트웨어 &lt;em&gt;위&lt;/em&gt;가 아니라 그 &lt;em&gt;아래&lt;/em&gt;에서.&lt;/p&gt;
&lt;h2 id="뿌리를-지키는-의식"&gt;뿌리를 지키는 의식
&lt;/h2&gt;&lt;p&gt;그 최종 루트를 어떻게 안전하게 다루는가 — 여기가 진짜 정교하다. 원리는 은행이든 DNS든 CA든 똑같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HSM&lt;/strong&gt;: 최상위 키가 탐침 방지 하드웨어 &lt;em&gt;안에서&lt;/em&gt; 태어나 &lt;strong&gt;밖으로 나오지 않는다.&lt;/strong&gt; 소프트웨어가 키를 &amp;lsquo;가지지&amp;rsquo; 않는다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;에어갭&lt;/strong&gt;: 루트 키는 네트워크에서 떼어 둔다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;M-of-N 분할 통제&lt;/strong&gt;: 한 사람이 루트를 쓸 수 없다. n명 중 k명이 각자의 조각(스마트카드)을 모아야 작동한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;키 세리머니&lt;/strong&gt;: 최상위 키를 쓰는 건 다인원·기록·촬영·감사되는 &lt;em&gt;의식&lt;/em&gt;이다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;거의 쓰지 않는다&lt;/strong&gt;: 루트는 아래 계층에 위임하고 잠가둔다. 일상 작업엔 절대 나오지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이게 추상이 아니다. &lt;strong&gt;DNSSEC 루트 키 세리머니&lt;/strong&gt;나 &lt;strong&gt;CA 루트 키 세리머니&lt;/strong&gt;를 찾아보면, 인류가 &amp;ldquo;위에 아무것도 없는 뿌리&amp;quot;를 만들고 지키는 방식이 문자 그대로 이렇다 — HSM, 다인원, 에어갭, 의식. (AWS 내부의 정확한 절차는 비공개지만, 이 산업 원리를 따른다.)&lt;/p&gt;
&lt;h2 id="mincloud가-진짜-서비스가-된다면"&gt;mincloud가 진짜 서비스가 된다면
&lt;/h2&gt;&lt;p&gt;지금 mincloud의 뿌리는 &amp;ldquo;로컬에서 바이너리를 실행하는 나&amp;quot;다. 이게 진짜 호스팅 클라우드가 되면, 그 뿌리는 &lt;strong&gt;사라지지 않고 옮겨간다&lt;/strong&gt; — &amp;ldquo;프로덕션 인프라와 시크릿 저장소를 통제하는 자&amp;quot;에게로.&lt;/p&gt;
&lt;p&gt;그때 반드시 바뀌는 것들:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;하드코딩 마스터 금지.&lt;/strong&gt; 지금의 well-known 기본값(&lt;code&gt;MINCLOUDTESTKEY0000A&lt;/code&gt;)은 로컬 편의일 뿐, 공개되면 백도어다. 프로덕션은 프로비저닝 때 &lt;strong&gt;유일한 루트를 생성&lt;/strong&gt;해 시크릿 매니저(KMS/Vault)에 넣는다. mincloud엔 이미 그 주입구가 있다 —&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;MINCLOUD_ROOT_ACCESS_KEY_ID / MINCLOUD_ROOT_SECRET_ACCESS_KEY
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;이미지엔 절대 안 넣고, 배포 시 시크릿으로만 주입한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;부트스트랩 문은 인터넷에 노출하지 않는다.&lt;/strong&gt; 서명 없는 동작은 운영자 전용. 세상을 마주하는 건 서명된 API뿐이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;시크릿 평문 저장 금지.&lt;/strong&gt; 지금 DynamoDB에 시크릿이 평문으로 들어가는 건 mock이라 넘어가는 것이고, 진짜라면 해시/KMS 암호화다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그리고 stakes가 오를수록 뿌리를 더 조인다. 작은 서비스면 &amp;ldquo;시크릿 매니저 + MFA + 감사&amp;quot;로 충분하고, 은행급이면 아까의 HSM+세리머니까지 간다. 요는, &lt;strong&gt;진짜 서비스가 된다고 부트스트랩을 벗어나는 게 아니라, &amp;ldquo;누가 인프라를 통제하는가&amp;quot;를 더 형식화하고 강화할 뿐&lt;/strong&gt;이라는 것이다.&lt;/p&gt;
&lt;h2 id="다음-이제-누가-계정을-만드는가"&gt;다음: 이제 누가 계정을 만드는가
&lt;/h2&gt;&lt;p&gt;제네시스 루트가 섰다. 그럼 6편에서 아무나 열던 그 &amp;ldquo;계정 만드는 문&amp;quot;을 다시 볼 수 있다. 진짜 AWS에서 계정 생성은 아무 문이 아니다 — &lt;strong&gt;관리 계정의 권한&lt;/strong&gt;이다. 관리 계정이 서명해서, 그 아래 멤버 계정을 찍는다.&lt;/p&gt;
&lt;p&gt;다음 편에서 그걸 만든다. 서명 없는 문은 이제 제네시스 하나에만 남기고, 나머지 계정은 &lt;strong&gt;관리 루트가 서명한 &lt;code&gt;CreateAccount&lt;/code&gt;&lt;/strong&gt; 로만 태어나게 한다. 그리고 그 문 앞에서, 이 시리즈에서 처음으로 &lt;strong&gt;&amp;ldquo;인증은 됐는데 권한이 없다&amp;rdquo;&lt;/strong&gt; 는 대답을 만나게 된다.&lt;/p&gt;</description></item></channel></rss>