<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>chnh.dev</title>
    <link>https://chnh.tistory.com/</link>
    <description>eeny meeny miny moe</description>
    <language>ko</language>
    <pubDate>Sun, 5 Apr 2026 17:18:38 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>chnh</managingEditor>
    <image>
      <title>chnh.dev</title>
      <url>https://tistory1.daumcdn.net/tistory/5950749/attach/3819052e65a74437988b7cec80f631f0</url>
      <link>https://chnh.tistory.com</link>
    </image>
    <item>
      <title>AWS 인스턴스 메타데이터와 IMDS</title>
      <link>https://chnh.tistory.com/25</link>
      <description>&lt;h1&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2019년 미국의 대형 금융지주회사 캐피탈 원이 해킹을 당해 1억명이 넘는 고객의 정보가 유출된 사례가 있습니다. 캐피탈원은 AWS를 사용중이었고, 공격자는 서버측 요청 위조 공격(SSRF) 취약점)을 이용해 &lt;b&gt;AWS EC2의 인스턴스 메타 데이터 서비스(IMDS)에 액세스하여 AWS Access Key에 접근&lt;/b&gt;할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 보안을 위한 WAF가 설정되어 있었으나 공격을 차단할 수 있는 적절한 설정이 되어있지 않았고, 자격 증명을&amp;nbsp;사용해 고객 정보가 저장된 S3 버킷에 액세스 할 수 있었습니다. (&lt;i&gt;참고: &lt;a href=&quot;https://systemweakness.com/case-study-aws-and-capital-one-c4ad6cb71c79&quot;&gt;Case Study: AWS and Capital One&lt;/a&gt;, &lt;a href=&quot;https://sarangcho.co.kr/142&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://sarangcho.co.kr/142&lt;/a&gt; )&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IMDS가 무엇이길래 액세스 정보까지 알아낼 수 있었던걸까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;b&gt;인스턴스 메타데이터와 IMDS&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;인스턴스 메타데이터는 말 그대로 &lt;b&gt;인스턴스에 대한 데이터&lt;/b&gt;&lt;/u&gt;입니다. 이 데이터를 사용해서 인스턴스를 구성하거나 관리 할 수 있고 사용자 데이터(user data)에도 액세스 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스를 시작하는 데 사용되는 &lt;b&gt;AMI ID,&lt;/b&gt; 인스턴스와 연결된&lt;b&gt; IAM 역할&lt;/b&gt;의 정보, 인스턴스와 연결된 IAM 역할이 있는 경우 &lt;b&gt;역할의 이름&lt;/b&gt;과 역할과 연결된 &lt;b&gt;임시 보안 자격 증명&lt;/b&gt;도 메타데이터에 포함됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1520&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGGAnr/btstqCW4MUa/wzgJJgj4j2y3TNFReVQqA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGGAnr/btstqCW4MUa/wzgJJgj4j2y3TNFReVQqA1/img.png&quot; data-alt=&quot;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#instance-metadata-security-credentials&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGGAnr/btstqCW4MUa/wzgJJgj4j2y3TNFReVQqA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGGAnr%2FbtstqCW4MUa%2FwzgJJgj4j2y3TNFReVQqA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;709&quot; height=&quot;136&quot; data-origin-width=&quot;1520&quot; data-origin-height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#instance-metadata-security-credentials&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 인스턴스 메타데이터를 조회하는 서비스를 인스턴스 메타데이터 서비스, IMDS(Instance Metadata Service)라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 A 인스턴스가 있다면, A 인스턴스 내에서만 인스턴스 메타데이터와 사용자 데이터에 접근할 수 있습니다. 다른 인스턴스에서는 A인스턴스 메타데이터에 접근할 수 없지만, A인스턴스에 직접 액세스 할 수만 있다면 그게 사용자이든, 인스턴스에서 실행중인 소프트웨어든 관계없이 메타데이터를 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이말인 즉슨 &lt;b&gt;❗️&lt;/b&gt;&lt;b&gt;공격자가 인스턴스 메타데이터에 접근할 수 있다면 임시 보안 자격 증명에 액세스할 수 있다는 뜻입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1120&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2bTlj/btstfQCSjUh/EUyNAAej9cSeEECwOEysqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2bTlj/btstfQCSjUh/EUyNAAej9cSeEECwOEysqk/img.png&quot; data-alt=&quot;인스턴스 메타데이터에서 IAM 자격증명을 탈취하는 방법 (출처: https://securitylabs.datadoghq.com/articles/misconfiguration-spotlight-imds)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2bTlj/btstfQCSjUh/EUyNAAej9cSeEECwOEysqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2bTlj%2FbtstfQCSjUh%2FEUyNAAej9cSeEECwOEysqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;655&quot; height=&quot;342&quot; data-origin-width=&quot;1120&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인스턴스 메타데이터에서 IAM 자격증명을 탈취하는 방법 (출처: https://securitylabs.datadoghq.com/articles/misconfiguration-spotlight-imds)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;실습 준비&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용을 인지한 상태로 실습을 진행해보겠습니다. 제공해주신 &lt;a href=&quot;https://ap-northeast-2.console.aws.amazon.com/cloudformation/home?region=ap-northeast-2#/stacks/new?stackName=iamlab&amp;amp;templateURL=https:%2F%2Fs3.ap-northeast-2.amazonaws.com%2Fcloudformation.cloudneta.net%2Fsecurity%2Fahss-ec2_2ea.yaml&quot;&gt;CloudFormation&lt;/a&gt;을 사용해 실습 환경을 구성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가지고 있는 SSH Keypair를 선택하고, 마지막 단계에서 &lt;b&gt;IAM 리소스 생성 승인&lt;/b&gt;을 체크하고 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2314&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccdPXK/btstk6kC23S/OMz22uH2EIVWevfyKxAaT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccdPXK/btstk6kC23S/OMz22uH2EIVWevfyKxAaT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccdPXK/btstk6kC23S/OMz22uH2EIVWevfyKxAaT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccdPXK%2Fbtstk6kC23S%2FOMz22uH2EIVWevfyKxAaT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;756&quot; height=&quot;102&quot; data-origin-width=&quot;2314&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 실행이 완료되면 &lt;code&gt;WebServer&lt;/code&gt;, &lt;code&gt;Attacker&lt;/code&gt; 2개의 EC2가 생성됩니다. 두 인스턴스 모두 80,22 번 포트에 대해 모든 IP를 허용하도록 설정되어 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 WebServer EC2의 메타데이터 서비스를 사용해 임시 자격 증명을 발급받고, Attacker인스턴스에서 WebServer의 임시 자격 증명을 사용해 S3에 접근하는 실습을 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;110&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5hNA5/btstkpx8ivV/JG2vEst5xhbrKej6f98Eek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5hNA5/btstkpx8ivV/JG2vEst5xhbrKej6f98Eek/img.png&quot; data-alt=&quot;WebServer EC2에는 IAM 역할이 연결되어 있으나 Attacker 인스턴스는 그렇지 않습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5hNA5/btstkpx8ivV/JG2vEst5xhbrKej6f98Eek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5hNA5%2Fbtstkpx8ivV%2FJG2vEst5xhbrKej6f98Eek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;704&quot; height=&quot;63&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;110&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;WebServer EC2에는 IAM 역할이 연결되어 있으나 Attacker 인스턴스는 그렇지 않습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IAM 자격증명 설정 되어 있는 PC에서 AWS CLI를 사용해 각각의 EC2 정보를 확인해보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 생성된 EC2의 IP 출력
aws cloudformation describe-stacks --stack-name iamlab --query 'Stacks[*].Outputs[*].OutputValue' |jq&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력한 IP를 사용해 EC2에 접속합니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;ssh -i &amp;lt;ssh-keyname&amp;gt;.pem ec2-user@&amp;lt;위 출력 IP&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;1. 인스턴스 메타데이터 조회&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[WebServer]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. IMDS의 IP주소인 &lt;code&gt;169.254.169.254&lt;/code&gt;를 사용해 실행중인 인스턴스의 메타데이터에는 어떤 것들이 있는지 확인해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ami-id, iam 등 조회할 수 있는 인스턴스 메타데이터 범주들이 표시됩니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;curl -s http://169.254.169.254/latest/meta-data/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 여기서 iam 정보를 호출하면 &lt;b&gt;인스턴스에 연결된 IAM 역할 이름을 반환&lt;/b&gt;합니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;curl -s http://169.254.169.254/latest/meta-data/iam/info&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ky80b/btstfeD2xzZ/kj3Skfdx9uyyRjlmj2jSKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ky80b/btstfeD2xzZ/kj3Skfdx9uyyRjlmj2jSKK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;254&quot; data-filename=&quot;edited_img 37.png&quot; data-widthpercent=&quot;74.14&quot; style=&quot;width: 73.281%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ky80b/btstfeD2xzZ/kj3Skfdx9uyyRjlmj2jSKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fky80b%2FbtstfeD2xzZ%2Fkj3Skfdx9uyyRjlmj2jSKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1574&quot; height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boqRzv/btstfcGgTSx/2XYb0rHeDJfilzYdkwlXUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boqRzv/btstfcGgTSx/2XYb0rHeDJfilzYdkwlXUK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;360&quot; data-filename=&quot;img 35.png&quot; data-widthpercent=&quot;25.86&quot; style=&quot;width: 25.5563%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boqRzv/btstfcGgTSx/2XYb0rHeDJfilzYdkwlXUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboqRzv%2FbtstfcGgTSx%2F2XYb0rHeDJfilzYdkwlXUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;778&quot; height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 2에서 획득한 IAM 역할 이름을 사용하여 임시 자격 증명을 발급해보겠습니다. Accesskey, Secretkey와 Token 정보가 모두 출력됩니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/IAMLabInstanceRole | jq&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 39.png&quot; data-origin-width=&quot;1990&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WwbaA/btstmGMz2U6/nUBKaMA2GfGfygpXWg1720/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WwbaA/btstmGMz2U6/nUBKaMA2GfGfygpXWg1720/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WwbaA/btstmGMz2U6/nUBKaMA2GfGfygpXWg1720/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWwbaA%2FbtstmGMz2U6%2FnUBKaMA2GfGfygpXWg1720%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;808&quot; height=&quot;313&quot; data-filename=&quot;img 39.png&quot; data-origin-width=&quot;1990&quot; data-origin-height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;2. 메타데이터를 통해 얻은 임시 자격 증명 사용&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[Attacker]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Attacker EC2에 접속해 S3 버킷 목록을 나열해보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;aws s3 ls&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh28LL/btstkq4QyVE/ztopfkdvgELxU1gt9hIi6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh28LL/btstkq4QyVE/ztopfkdvgELxU1gt9hIi6K/img.png&quot; data-alt=&quot;자격증명이 없기 때문에 aws configure을 사용해 자격증명을 구성하라는 안내가 출력됩니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh28LL/btstkq4QyVE/ztopfkdvgELxU1gt9hIi6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh28LL%2Fbtstkq4QyVE%2FztopfkdvgELxU1gt9hIi6K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;693&quot; height=&quot;54&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;자격증명이 없기 때문에 aws configure을 사용해 자격증명을 구성하라는 안내가 출력됩니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. WebServer 인스턴스에서 탈취(?)한 임시 자격증명을 설정하고, S3 버킷 목록을 나열해보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 위에서 출력된 AccessKeyId , SecretAccessKey , SessionToken 으로 임시자격증명 적용
export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
export AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}

# s3 버킷 조회
aws s3 ls&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1152&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA5zu9/btstksO3TbF/3J9zKTxnjvex3H6e10KGlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA5zu9/btstksO3TbF/3J9zKTxnjvex3H6e10KGlk/img.png&quot; data-alt=&quot;버킷 목록이 정상적으로 출력됩니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA5zu9/btstksO3TbF/3J9zKTxnjvex3H6e10KGlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA5zu9%2FbtstksO3TbF%2F3J9zKTxnjvex3H6e10KGlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;707&quot; height=&quot;88&quot; data-origin-width=&quot;1152&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버킷 목록이 정상적으로 출력됩니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. EC2에 연결된 IAM 역할은 없지만 WebServer 인스턴스의 임시 자격증명을 사용해 S3 버킷 목록 나열이 가능했다는 것을 알 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 어떤 인스턴스의 ID와 역할인가?
aws sts get-caller-identity | jq&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_img 42.png&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MqSBP/btstgi68d5z/Dazx6bASWFUuWmSSnyb1z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MqSBP/btstgi68d5z/Dazx6bASWFUuWmSSnyb1z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MqSBP/btstgi68d5z/Dazx6bASWFUuWmSSnyb1z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMqSBP%2Fbtstgi68d5z%2FDazx6bASWFUuWmSSnyb1z1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;102&quot; data-filename=&quot;edited_img 42.png&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;3. CloudTrail 로그 활성화&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS상에서 일어나는 모든 동작들은 API성으로 이루어져 CloudTrail에 기록됩니다. CloudTrail 콘솔에서 &lt;code&gt;AssumeRole&lt;/code&gt; API 호출에 대한 기록을 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;AssumeRole 이벤트란?&lt;br /&gt;&lt;/b&gt;사용자 또는 AWS 서비스가 IAM 역할을 맡을 때 생성되는 이벤트로, 역할이 수임되면 API 요청에 사용할 수 있는 임시 보안 자격 증명이 발급됩니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언제 어디서 어떤 주체에 의해 이벤트가 발생했는지 상세하게 기록된 것을 확인할 수 있습니다. 작업 주체, 발급된 자격증명 정보 등의 내용이 포함됩니다. 특정 동작을 필터링해서 알람을 받도록 설정하는 것도 자격 증명이 남용되는 것을 방지하는 하나의 방법이 될 수 있을 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 48.png&quot; data-origin-width=&quot;2200&quot; data-origin-height=&quot;1314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cb2CNE/btstkVDAGHP/HvPQkXEc7ouMxtsSoHtnj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cb2CNE/btstkVDAGHP/HvPQkXEc7ouMxtsSoHtnj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cb2CNE/btstkVDAGHP/HvPQkXEc7ouMxtsSoHtnj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcb2CNE%2FbtstkVDAGHP%2FHvPQkXEc7ouMxtsSoHtnj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2200&quot; height=&quot;1314&quot; data-filename=&quot;img 48.png&quot; data-origin-width=&quot;2200&quot; data-origin-height=&quot;1314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;4. IMDS 취약점 해결 방안&lt;/b&gt;&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 인스턴스 메타데이터를 요청할 때 IMDSv2를 사용해야 하도록 설정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스 메타데이터에 접근할 때 IMDSv1과 v2 모두 사용할 수 있지만 OWASP에서는 보안상 &lt;b&gt;IMDSv2를 사용하는 것을 권장&lt;/b&gt;하고 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;인스턴스 메타데이터 서비스 버전 1(IMDSv1) - 요청/응답 방법&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EC2인스턴스에서 IMDS에 요청하면 요청 결과에 대해 응답을 보냅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;인스턴스 메타데이터 서비스 버전 2(IMDSv2) &amp;ndash; 세션 지향 방법&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;소프트웨어는 IMDSv2에 대한 HTTP PUT 요청으로 세션을 시작&lt;/li&gt;
&lt;li&gt;IMDSv2는 EC2 인스턴스에서 실행되는 소프트웨어에 비밀 토큰을 반환&lt;/li&gt;
&lt;li&gt;소프트웨어는 해당 토큰을 암호로 사용하여 IMDSv2에 메타데이터 및 자격 증명을 요청&lt;/li&gt;
&lt;li&gt;토큰을 사용하는 프로세스가 종료되면 세션과 해당 토큰 삭제&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔에서 &lt;b&gt;[인스턴스 설정]&lt;/b&gt; &amp;gt; &lt;b&gt;[인스턴스 메타데이터 옵션 수정]&lt;/b&gt; &amp;gt; &lt;b&gt;[인스턴스 메타데이터 서비스]&lt;/b&gt; 에서 &lt;u&gt;&lt;b&gt;IMDSv2&lt;/b&gt; 를 &lt;b&gt;필수&lt;/b&gt;&lt;/u&gt;로 설정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SnxuZ/btstqwioWZL/yfdFEVeXE31oZwyaXfe31k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SnxuZ/btstqwioWZL/yfdFEVeXE31oZwyaXfe31k/img.png&quot; style=&quot;width: 39.8585%; margin-right: 10px;&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;1124&quot; data-filename=&quot;img 43.png&quot; data-widthpercent=&quot;40.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SnxuZ/btstqwioWZL/yfdFEVeXE31oZwyaXfe31k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSnxuZ%2FbtstqwioWZL%2FyfdFEVeXE31oZwyaXfe31k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;984&quot; height=&quot;1124&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qFB0n/btstpFNtE3X/SHoHHgK7aBjxjsTHG9Dzs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qFB0n/btstpFNtE3X/SHoHHgK7aBjxjsTHG9Dzs1/img.png&quot; data-origin-width=&quot;1070&quot; data-origin-height=&quot;826&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;59.67&quot; style=&quot;width: 58.9787%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qFB0n/btstpFNtE3X/SHoHHgK7aBjxjsTHG9Dzs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqFB0n%2FbtstpFNtE3X%2FSHoHHgK7aBjxjsTHG9Dzs1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1070&quot; height=&quot;826&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# IMDSv1
curl http://169.254.169.254/latest/meta-data/

# IMDSv2
TOKEN=`curl -X PUT &quot;http://169.254.169.254/latest/api/token&quot; -H &quot;X-aws-ec2-metadata-token-ttl-seconds: 21600&quot;` \
&amp;amp;&amp;amp; curl -H &quot;X-aws-ec2-metadata-token: $TOKEN&quot; -v http://169.254.169.254/latest/meta-data/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMQvgh/btstlOc85p7/2Jof4IhBOXv6bKCF5Cl3QK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMQvgh/btstlOc85p7/2Jof4IhBOXv6bKCF5Cl3QK/img.png&quot; data-alt=&quot;IMDSv1의 명령어로 호출하자 401-Unauthorized 에러가 발생합니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMQvgh/btstlOc85p7/2Jof4IhBOXv6bKCF5Cl3QK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMQvgh%2FbtstlOc85p7%2F2Jof4IhBOXv6bKCF5Cl3QK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;725&quot; height=&quot;236&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IMDSv1의 명령어로 호출하자 401-Unauthorized 에러가 발생합니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 50.png&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;1344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvf6vY/btstqEHzyuA/IkEVbg0JGvkCFzYmw6tp5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvf6vY/btstqEHzyuA/IkEVbg0JGvkCFzYmw6tp5K/img.png&quot; data-alt=&quot;IMDSv2 명령어로 호출하자 정상적으로 메타데이터 범주가 출력됩니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvf6vY/btstqEHzyuA/IkEVbg0JGvkCFzYmw6tp5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbvf6vY%2FbtstqEHzyuA%2FIkEVbg0JGvkCFzYmw6tp5K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;732&quot; height=&quot;459&quot; data-filename=&quot;img 50.png&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;1344&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IMDSv2 명령어로 호출하자 정상적으로 메타데이터 범주가 출력됩니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IMDSv2 명령어를 사용해 ami-id를 확인해보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;curl -H &quot;X-aws-ec2-metadata-token: $TOKEN&quot; http://169.254.169.254/latest/meta-data/ami-id&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1908&quot; data-origin-height=&quot;74&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Zva75/btstkWP3RsR/7eITykt01GiWWp5KhkuDN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Zva75/btstkWP3RsR/7eITykt01GiWWp5KhkuDN1/img.png&quot; data-alt=&quot;ami id가 정상적으로 출력됩니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Zva75/btstkWP3RsR/7eITykt01GiWWp5KhkuDN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZva75%2FbtstkWP3RsR%2F7eITykt01GiWWp5KhkuDN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1908&quot; height=&quot;74&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1908&quot; data-origin-height=&quot;74&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ami id가 정상적으로 출력됩니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  모든 인스턴스에 콘솔 클릭클릭 노가다를 하는 것은 상당히 비효율적이기에 &lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/ExamplePolicies_EC2.html#iam-example-instance-metadata-requireIMDSv2&quot;&gt;IAM 정책 또는 SCP에서 IAM 조건 키를 사용&lt;/a&gt;하여 &lt;b&gt;IMDSv2를 사용해야 하도록 구성된 경우에만 인스턴스를 시작할 수 있도록&lt;/b&gt; 설정하는 방법도 있습니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
               {
            &quot;Sid&quot;: &quot;RequireImdsV2&quot;,
            &quot;Effect&quot;: &quot;Deny&quot;,
            &quot;Action&quot;: &quot;ec2:RunInstances&quot;,
            &quot;Resource&quot;: &quot;arn:aws:ec2:*:*:instance/*&quot;,
            &quot;Condition&quot;: {
                &quot;StringNotEquals&quot;: {
                    &quot;ec2:MetadataHttpTokens&quot;: &quot;required&quot;
                }
            }
        }
    ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. IMDS 비활성화&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔에서 &lt;b&gt;[인스턴스 설정]&lt;/b&gt; &amp;gt; &lt;b&gt;[인스턴스 메타데이터 옵션 수정]&lt;/b&gt; &amp;gt; &lt;b&gt;[인스턴스 메타데이터 서비스] 항목&lt;/b&gt;을 &lt;u&gt;&lt;b&gt;비활성화&lt;/b&gt;&lt;/u&gt;하여 인스턴스에서 IMDS를 사용하지 못하도록 설정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ci1ZpP/btstq9mVDgK/dgoAajz32Hbr1Vkp61ldF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ci1ZpP/btstq9mVDgK/dgoAajz32Hbr1Vkp61ldF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ci1ZpP/btstq9mVDgK/dgoAajz32Hbr1Vkp61ldF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci1ZpP%2Fbtstq9mVDgK%2FdgoAajz32Hbr1Vkp61ldF1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;547&quot; height=&quot;408&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Webserver] 인스턴스에서 메타데이터 서비스를 비활성화하고 다시 메타데이터를 조회해봤습니다. 전과 달리 403 - Forbidden 에러가 발생합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvP4kG/btstkrbztKG/hk3SmBfdzoxWbf7EkbO6ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvP4kG/btstkrbztKG/hk3SmBfdzoxWbf7EkbO6ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvP4kG/btstkrbztKG/hk3SmBfdzoxWbf7EkbO6ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvP4kG%2FbtstkrbztKG%2Fhk3SmBfdzoxWbf7EkbO6ik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;650&quot; height=&quot;192&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. IMDS 액세스 제한&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 방화벽 규칙을 사용해 IMDS의 IP주소인 &lt;code&gt;169.254.169.254&lt;/code&gt; 자체에 접근하지 못하도록 설정할 수 있습니다. &lt;i&gt;(참고: &lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#instance-metadata-limiting-access&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IMDS 액세스 제한&lt;/a&gt;)&lt;/i&gt;&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부끄럽지만 인스턴스 메타데이터 옵션에 이렇게 다양한 정보가 존재하는지, 해킹의 포인트가 될 수 있다는 사실을 모르고 살았습니다. 공격자의 입장에서 생각해보는게 보안을 강화하는 첫걸음이라는 생각이 들었습니다. 스터디 2주차밖에 되지 않았지만 생각의 지평이 크게 확장되고 있다는 느낌이 듭니다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더불어 정답이 없다는 생각도 들어요. 그래서 더 어려운 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 있는 회사에서는 SSM(Session Manager)를 사용한 인스턴스 접속이 액세스 키를 관리할 필요가 없기 때문에 보안상 우수하다고 여기는데, 분리되지 않은 단말기에서 인스턴스에 접근 가능하기 때문에 SSM 사용을 제한해야한다는 의견도 있더라구요. 다들 어떻게 사용하고 계시는지 궁금합니다. !&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;+) 스크린샷에 있는 EC2와 기타 정보들은 모두 삭제된 리소스입니다.&amp;nbsp;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666; text-align: center;&quot;&gt;CloudNet@팀의 AHSS(AWS Hacking &amp;amp; Security 스터디)&amp;nbsp; 학습 내용과 제가 공부한 내용을 정리한 글입니다. &lt;br /&gt;더 좋은 방법이나 틀린 내용이 있으면 말씀해주세요 :)&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html&quot;&gt;[AWS Docs] 인스턴스 메타데이터 검색&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://aws.amazon.com/ko/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/&quot;&gt;[AWS Security Blog] EC2 인스턴스 메타데이터 서비스의 향상된 기능을 통해 개방형 방화벽, 역방향 프록시 및 SSRF 취약성에 대한 심층적인 방어 기능을 추가&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html&quot;&gt;[AWS Docs] API_AssumeRole&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>☁️ AWS</category>
      <category>ahss</category>
      <category>AWS</category>
      <category>IMDS</category>
      <category>Security</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/25</guid>
      <comments>https://chnh.tistory.com/25#entry25comment</comments>
      <pubDate>Thu, 7 Sep 2023 17:09:45 +0900</pubDate>
    </item>
    <item>
      <title>AWS S3 취약점 및 보안</title>
      <link>https://chnh.tistory.com/24</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/ko/pm/serv-s3/?trk=024bf255-8753-410e-9b2f-8015932510e8&amp;amp;sc_channel=ps&amp;amp;ef_id=Cj0KCQjw6KunBhDxARIsAKFUGs8cbSQOsHFoEuSORikS1EgyA0AKKeaNdpkHfdmORHfxL-W0UVA8yocaAk_nEALw_wcB:G:s&amp;amp;s_kwcid=AL!4422!3!588924203916!e!!g!!s3!16390143117!134236388536&quot;&gt;S3&lt;/a&gt;(Simple Storage Service)는 AWS의 무제한 객체 기반 스토리지 서비스입니다. 데이터 레이크, 웹 사이트, 모바일 애플리케이션, 백업 및 복원, 빅 데이터 분석 등 다양한 용도로 사용이 가능한 AWS의 대표 서비스 중 하나인데요, 널리 사용되는 만큼 S3 데이터 유출 사고 역시 빈번하게 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3는 다양한 방법의 접근 제어 및 관리 기능을 제공하고 있어 세분화된 제어가 가능합니다. 다소 복잡할 수 있기 때문에 상황에 적절한 방법을 택해 사용할 수 있어야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1주차에서는 S3 접근을 통제하는 방법을 알아보고 통제 방법에 따라 다양한 조건에서 실습을 진행했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;b&gt;실습 준비&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS 자격 증명이 구성되어 있는 로컬PC&lt;/b&gt;와 &lt;b&gt;AWS 자격 증명이 구성되지 않은 EC2&lt;/b&gt;가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AWS 환경 구성은 스터디장인 가시다님이 제공해주신 &lt;a href=&quot;https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/security/ahss-ec2.yaml&quot;&gt;CloudFormation 스택&lt;/a&gt;을 사용해 배포했습니다.)&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;S3의 접근 통제&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 버킷, 객체 등 모든 S3 리소스는 프라이빗으로 생성되며, 이를 생성한 계정인 리소스 소유자만 해당 리소스에 접근할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3의 접근 통제 옵션은 크게 &lt;b&gt;리소스 기반 정책&lt;/b&gt;과 &lt;b&gt;사용자 기반 정책(IAM)&lt;/b&gt;으로 나눠 볼 수 있습니다. &lt;b&gt;ACL이나 버킷 정책&lt;/b&gt;은 &lt;b&gt;리소스 기반 정책&lt;/b&gt;으로, &lt;b&gt;IAM 정책&lt;/b&gt;은 &lt;b&gt;사용자 기반 정책&lt;/b&gt;으로 생각할 수 있습니다. 이 두 옵션을 조합해서 사용할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;383&quot; data-origin-height=&quot;359&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b17yTU/btssGAzD7jI/RwtXwm7bWjzZcv7KzORhj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b17yTU/btssGAzD7jI/RwtXwm7bWjzZcv7KzORhj1/img.png&quot; data-alt=&quot;리소스 기반 정책 - 버킷 정책과 ACL(액세스 제어 목록)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b17yTU/btssGAzD7jI/RwtXwm7bWjzZcv7KzORhj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb17yTU%2FbtssGAzD7jI%2FRwtXwm7bWjzZcv7KzORhj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;383&quot; height=&quot;359&quot; data-origin-width=&quot;383&quot; data-origin-height=&quot;359&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;리소스 기반 정책 - 버킷 정책과 ACL(액세스 제어 목록)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;277&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6JbKy/btssDQiBAks/wkMk8MvN3hWgQzkrLG8ESK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6JbKy/btssDQiBAks/wkMk8MvN3hWgQzkrLG8ESK/img.png&quot; data-alt=&quot;사용자 정책 - IAM으로 S3 리소스에 대한 액세스 관리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6JbKy/btssDQiBAks/wkMk8MvN3hWgQzkrLG8ESK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6JbKy%2FbtssDQiBAks%2FwkMk8MvN3hWgQzkrLG8ESK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;371&quot; height=&quot;277&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;277&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사용자 정책 - IAM으로 S3 리소스에 대한 액세스 관리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;객체&amp;amp;버킷 ACL&lt;/b&gt;&lt;i&gt;(권장하지 않음)&lt;/i&gt;: 액세스 제어 목록(ACL)을 사용하여 개별 객체 or 버킷에 대한 액세스를 제어&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버킷 정책&lt;/b&gt;: 단일 S3 버킷 내 모든 객체에 대한 권한 구성, (특정 작업, 요청 IP 등 다양한 조건을 기반으로 제어 가능)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IAM 정책&lt;/b&gt;: 사용자의 S3 액세스 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;i&gt;✔️ 만약 리소스 기반 정책과 사용자 기반 정책이 상충한다면 어떻게 될까요 ?&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동일 계정 내인지, Cross Account 상황인지에 따라 결과가 달라집니다.&lt;br /&gt;&lt;b&gt;내가 접근하려는 리소스가 내 계정안에 있는 리소스라면&lt;/b&gt; 리소스 기반과 정책 사용자 기반 정책의 &lt;b&gt;합집합&lt;/b&gt;이,&lt;br /&gt;&lt;b&gt;접근하려는 리소스가 다른 계정에 위치했다면&lt;/b&gt; 리소스 기반과 정책 사용자 기반 정책의 &lt;b&gt;교집합&lt;/b&gt;이 적용됩니다.&lt;br /&gt;&lt;i&gt;참고: &lt;a href=&quot;https://youtu.be/zIZ6_tYujts?si=8jgNsINzq3zSvWJU&amp;amp;t=905&quot;&gt;https://youtu.be/zIZ6_tYujts?si=8jgNsINzq3zSvWJU&amp;amp;t=905&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;1. S3 취약점&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷 ACL, 객체 ACL 활성화 유무와 버킷 정책을 사용하여 테스트했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 버킷 생성과 '모든 퍼블릭 액세스 차단'&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습을 위해 S3 버킷을 먼저 생성해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 IAM 자격증명이 설정 되어 있는 &lt;b&gt; ️&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;로컬 PC의 터미널에서 AWS CLI로 버킷을 생성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;aws s3api&lt;/code&gt; 명령어는 &lt;code&gt;aws s3&lt;/code&gt; 보다 더 세분화된 내용과 작업을 가능하게 합니다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;# 버킷 생성
NICKNAME=&amp;lt;자신의닉네임&amp;gt;
aws s3 mb s3://ahss-$NICKNAME --region ap-northeast-2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdXKi2/btssGkjw9bz/GweFO4v4QINQPzW83kx9MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdXKi2/btssGkjw9bz/GweFO4v4QINQPzW83kx9MK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdXKi2/btssGkjw9bz/GweFO4v4QINQPzW83kx9MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdXKi2%2FbtssGkjw9bz%2FGweFO4v4QINQPzW83kx9MK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;85&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷을 생성하면 &lt;b&gt;기본적으로 퍼블릭 액세스가 차단&lt;/b&gt;되어있습니다.&lt;/p&gt;
&lt;pre class=&quot;dsconfig&quot;&gt;&lt;code&gt;aws s3api get-public-access-block --bucket ahss-$NICKNAME | jq&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjCvKl/btssGBrNbdo/kdsFAJopuLFWSxst12zAY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjCvKl/btssGBrNbdo/kdsFAJopuLFWSxst12zAY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjCvKl/btssGBrNbdo/kdsFAJopuLFWSxst12zAY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjCvKl%2FbtssGBrNbdo%2FkdsFAJopuLFWSxst12zAY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;706&quot; height=&quot;197&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3 콘솔 [권한] 탭에서도 확인이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;816&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nG3bP/btssIn02UIJ/fwBn7aKzcANazVRK2VwJR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nG3bP/btssIn02UIJ/fwBn7aKzcANazVRK2VwJR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nG3bP/btssIn02UIJ/fwBn7aKzcANazVRK2VwJR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnG3bP%2FbtssIn02UIJ%2FfwBn7aKzcANazVRK2VwJR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;274&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;816&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 로컬 PC에서 파일을 만들어 S3로 업로드 해보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 파일 생성
echo &quot;memo1&quot; &amp;gt; memo1.txt
echo &quot;memo2&quot; &amp;gt; memo2.txt
echo &quot;memo3&quot; &amp;gt; memo3.txt

# S3로 업로드
aws s3 cp memo1.txt s3://ahss-$NICKNAME
aws s3 cp memo2.txt s3://ahss-$NICKNAME
aws s3 cp memo3.txt s3://ahss-$NICKNAME&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccs544/btssBlKbi26/xSz1igN7nRD8Spb2KClO31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccs544/btssBlKbi26/xSz1igN7nRD8Spb2KClO31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccs544/btssBlKbi26/xSz1igN7nRD8Spb2KClO31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fccs544%2FbtssBlKbi26%2FxSz1igN7nRD8Spb2KClO31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;149&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;퍼블릭 엑세스가 차단되어 있지만 IAM 자격증명이 설정되어 있는 상태이기 때문에&lt;/b&gt; 정상적으로 파일이 업로드 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 업로드 된 객체들을 확인해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ 모든 퍼블릭 액세스 차단 활성화 상태&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  EC2 &lt;/b&gt;(IAM 자격증명 X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOTB3h/btssDNmaJDr/olpWXyzyKM4nMDQgJnrxR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOTB3h/btssDNmaJDr/olpWXyzyKM4nMDQgJnrxR1/img.png&quot; data-alt=&quot;EC2에는 자격증명이 구성되지 않은 상태&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOTB3h/btssDNmaJDr/olpWXyzyKM4nMDQgJnrxR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOTB3h%2FbtssDNmaJDr%2FolpWXyzyKM4nMDQgJnrxR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;680&quot; height=&quot;64&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;108&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;EC2에는 자격증명이 구성되지 않은 상태&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 업로드 객체 확인 
aws s3 ls s3://ahss-$NICKNAME --human-readable&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtAbpm/btssGBr2iTu/gcZMr0PZkrzgsJFTi30GT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtAbpm/btssGBr2iTu/gcZMr0PZkrzgsJFTi30GT1/img.png&quot; data-alt=&quot;모든 퍼블릭 액세스 차단 활성화 / EC2 / 자격증명 X&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtAbpm/btssGBr2iTu/gcZMr0PZkrzgsJFTi30GT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdtAbpm%2FbtssGBr2iTu%2FgcZMr0PZkrzgsJFTi30GT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;705&quot; height=&quot;68&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 퍼블릭 액세스 차단 활성화 / EC2 / 자격증명 X&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 서명 없이 업로드 객체 확인 
aws s3 ls s3://ahss-$NICKNAME --human-readable --no-sign-request&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;--no-sign-request&lt;/code&gt; 옵션은 AWS 서비스 엔드포인트에 대한 HTTP 요청 서명을 비활성화하는 부울 스위치입니다. 이렇게 하면 보안 인증이 로드되는 것을 방지할 수 있습니다.&amp;nbsp; 해당 옵션값을 주자 아예 bucket을 찾지 못합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;190&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bX0V3C/btssMSfmNSo/XIDD0wgiYWt7CV6kSwxo0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bX0V3C/btssMSfmNSo/XIDD0wgiYWt7CV6kSwxo0k/img.png&quot; data-alt=&quot;모든 퍼블릭 액세스 차단 활성화 / EC2 - 자격증명 X /&amp;amp;amp;nbsp;--no-sign-request 옵션 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bX0V3C/btssMSfmNSo/XIDD0wgiYWt7CV6kSwxo0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbX0V3C%2FbtssMSfmNSo%2FXIDD0wgiYWt7CV6kSwxo0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;698&quot; height=&quot;116&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;190&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 퍼블릭 액세스 차단 활성화 / EC2 - 자격증명 X /&amp;amp;nbsp;--no-sign-request 옵션 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ 모든 퍼블릭 액세스 차단 활성화 상태&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; ️ PC &lt;/b&gt;(IAM 자격증명 O)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IAM 자격증명이 설정되어 있어 정상적으로 조회가 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XCMys/btssMCp73jX/GdiOACedQwxVomsWQodYA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XCMys/btssMCp73jX/GdiOACedQwxVomsWQodYA1/img.png&quot; data-alt=&quot;모든 퍼블릭 액세스 차단 활성화 / PC - 자격증명 O&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XCMys/btssMCp73jX/GdiOACedQwxVomsWQodYA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXCMys%2FbtssMCp73jX%2FGdiOACedQwxVomsWQodYA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;668&quot; height=&quot;108&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 퍼블릭 액세스 차단 활성화 / PC - 자격증명 O&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서명을 비활성화하자 Access가 거부되는 것을 확인할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4uyWy/btssLDpfZ5M/2CB5xKT8HUTMABgO4WefC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4uyWy/btssLDpfZ5M/2CB5xKT8HUTMABgO4WefC1/img.png&quot; data-alt=&quot;모든 퍼블릭 액세스 차단 활성화 / PC - 자격증명 O / --no-sign-request 옵션 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4uyWy/btssLDpfZ5M/2CB5xKT8HUTMABgO4WefC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4uyWy%2FbtssLDpfZ5M%2F2CB5xKT8HUTMABgO4WefC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;665&quot; height=&quot;143&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;234&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 퍼블릭 액세스 차단 활성화 / PC - 자격증명 O / --no-sign-request 옵션 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 URL을 사용해 웹으로 접근하면 &lt;code&gt;AccessDenied&lt;/code&gt;가 표시됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HkWhD/btsswTADdlH/KdmMYQZXU1hhctLlthO8MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HkWhD/btsswTADdlH/KdmMYQZXU1hhctLlthO8MK/img.png&quot; data-alt=&quot;모든 퍼블릭 액세스 차단 활성화 / 객체 URL로 접근&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HkWhD/btsswTADdlH/KdmMYQZXU1hhctLlthO8MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHkWhD%2FbtsswTADdlH%2FKdmMYQZXU1hhctLlthO8MK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;690&quot; height=&quot;146&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;356&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 퍼블릭 액세스 차단 활성화 / 객체 URL로 접근&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 콘솔에서 버킷의 퍼블릭 액세스를 차단을 해제해보겠습니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2220&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbwQBX/btssB154q6b/iwSfm6ThXlQkNQJk76YkrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbwQBX/btssB154q6b/iwSfm6ThXlQkNQJk76YkrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbwQBX/btssB154q6b/iwSfm6ThXlQkNQJk76YkrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbwQBX%2FbtssB154q6b%2FiwSfm6ThXlQkNQJk76YkrK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;768&quot; height=&quot;266&quot; data-origin-width=&quot;2220&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  모든 퍼블릭 액세스 차단 비활성&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  EC2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;(IAM 자격증명 X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷의 모든 퍼블릭 액세스 차단 설정을 비활성화 했으나 결과는 동일합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVUYzU/btssGvMi6d2/Y6aygYKqTJ8HkK4V8J8Ja0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVUYzU/btssGvMi6d2/Y6aygYKqTJ8HkK4V8J8Ja0/img.png&quot; data-alt=&quot;모든 퍼블릭 액세스 차단 비활성화 / EC2 - 자격증명 X&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVUYzU/btssGvMi6d2/Y6aygYKqTJ8HkK4V8J8Ja0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVUYzU%2FbtssGvMi6d2%2FY6aygYKqTJ8HkK4V8J8Ja0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;69&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 퍼블릭 액세스 차단 비활성화 / EC2 - 자격증명 X&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Zc2N8/btssLKIGAjH/Rv2VDHnIDFaWEvLdyCaevK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Zc2N8/btssLKIGAjH/Rv2VDHnIDFaWEvLdyCaevK/img.png&quot; data-alt=&quot;모든 퍼블릭 액세스 차단 비활성화 / EC2 - 자격증명 X / --no-sign-request 옵션 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Zc2N8/btssLKIGAjH/Rv2VDHnIDFaWEvLdyCaevK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZc2N8%2FbtssLKIGAjH%2FRv2VDHnIDFaWEvLdyCaevK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;113&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 퍼블릭 액세스 차단 비활성화 / EC2 - 자격증명 X / --no-sign-request 옵션 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; ️ PC&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;(IAM 자격증명 O), 객체 URL로 접근시에도 전과 동일한 결과가 표시됐습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권한 개요가&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #16191f; text-align: left;&quot;&gt;&lt;b&gt;객체를 퍼블릭으로 설정할 수 있음&lt;/b&gt;으로&amp;nbsp;&lt;/span&gt;변경되으나 객체가 자동으로 공개되지는 않았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dgytUt/btssLHrEOit/HKqHkxlkAq8FKMNRrHjWd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dgytUt/btssLHrEOit/HKqHkxlkAq8FKMNRrHjWd0/img.png&quot; data-origin-width=&quot;1056&quot; data-origin-height=&quot;242&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.463%; margin-right: 10px;&quot; data-widthpercent=&quot;48.02&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dgytUt/btssLHrEOit/HKqHkxlkAq8FKMNRrHjWd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdgytUt%2FbtssLHrEOit%2FHKqHkxlkAq8FKMNRrHjWd0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1056&quot; height=&quot;242&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbHHw9/btssMEVOFRl/xiKIrZdJAKHdFXoVDISE0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbHHw9/btssMEVOFRl/xiKIrZdJAKHdFXoVDISE0K/img.png&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;224&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.3742%;&quot; data-widthpercent=&quot;51.98&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbHHw9/btssMEVOFRl/xiKIrZdJAKHdFXoVDISE0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbHHw9%2FbtssMEVOFRl%2FxiKIrZdJAKHdFXoVDISE0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1058&quot; height=&quot;224&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;좌) 모든 퍼블릭 액세스 차단 활성화 / 우) 모든 퍼블릭 액세스 차단 비활성화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;그럼 여기서 의미하는 '퍼블릭'은 무엇인지 의문이 들었습니다. &lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;AWS에서 정의하는 &lt;/span&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/access-control-block-public-access.html#access-control-block-public-access-policy-status&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;퍼블릭의 의미&lt;/span&gt;&lt;/a&gt; &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;는 다음과 같습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ACL
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;미리 정의된 AllUsers&lt;/b&gt; 또는 &lt;b&gt;AuthenticatedUsers 그룹&lt;/b&gt;의 구성원에게 권한을 부여하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;버킷 정책
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버킷 정책은 &lt;b&gt;기본적으로 퍼블릭으로 평가&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;퍼블릭이 아닌 것으로 평가되려면 ? &lt;br /&gt;버킷 정책에서 AWS 보안 주체, SourceIP, SourceArn 등 하나 이상에 대한 &lt;b&gt;고정 값&lt;/b&gt;을 부여해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 퍼블릭
{
        &quot;Principal&quot;: &quot;*&quot;, 
        &quot;Resource&quot;: &quot;*&quot;, 
        &quot;Action&quot;: &quot;s3:PutObject&quot;, 
        &quot;Effect&quot;: &quot;Allow&quot;, 
        &quot;Condition&quot;: { &quot;StringLike&quot;: {&quot;aws:SourceVpc&quot;: &quot;vpc-*&quot;}}
    }

# 퍼블릭이 아님 
{
        &quot;Principal&quot;: &quot;*&quot;, 
        &quot;Resource&quot;: &quot;*&quot;, 
        &quot;Action&quot;: &quot;s3:PutObject&quot;, 
        &quot;Effect&quot;: &quot;Allow&quot;, 
        &quot;Condition&quot;: {&quot;StringEquals&quot;: {&quot;aws:SourceVpc&quot;: &quot;vpc-91237329&quot;}}
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;모든 퍼블릭 액세스 차단을 비활성화하면 &lt;b&gt;객체에 공개적으로 접근 가능할 수 있다는 가능성이 생길 뿐&lt;/b&gt;,&lt;/u&gt; &lt;b&gt;객체에 대한 접근 가능 여부는 버킷 정책 등 여러 요소에 따라 달라진다는 것을 알 수 있었습니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제부터 ACL과 버킷 정책에 따라 객체에 대한 접근 가능여부가 어떻게 달라지는지 확인해보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. ACL 활성화&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;i&gt;&lt;b&gt; ACL은 언제쓸까요 ?&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;&lt;br /&gt;특별한 이유가 없다면 ACL을 비활성화하는 것이 좋습니다. ACL을 사용하면 IAM과 버킷 정책 외에 추가로 액세스를 제어할 수 있는 계층이 생성되는데, 이렇게 되면 관리의 복잡성과 구성 오류의 위험성이 증가하게 되기 때문입니다.&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;다만 A계정에서 B계정이 소유한 버킷에 객체를 업로드할 때, &lt;span style=&quot;background-color: #ffffff; color: #232f3e; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;특정 작업을 수행할 수 있는 권한을 Amazon CloudFront와 같은 AWS 서비스에 부여할 때 객체 ACL을 사용하게 됩니다. 자세한 내용은&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;i&gt;&amp;nbsp;&lt;a href=&quot;https://repost.aws/ko/knowledge-center/s3-object-acl-use-cases&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Amazon S3에서 객체 ACL을 사용하는 사용 사례에는 어떤 것이 있나요?&lt;/a&gt;&lt;/i&gt;를 참고해주세요.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 실습에서는 ACL을 활성화하고 객체별 소유권을 제어해봤습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. AWS 콘솔에서&lt;b&gt; [권한] &amp;gt; 객체 소유권 편집&lt;/b&gt;을 선택합니다. ACL을 활성화하고 ACL 편집을 통해 모든 사람(퍼블릭 액세스)이 객체를 나열할 수 있도록 설정합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1898&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BAWoP/btssUa8jRr3/7KFyAcZbIJcKYabAHN5jXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BAWoP/btssUa8jRr3/7KFyAcZbIJcKYabAHN5jXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BAWoP/btssUa8jRr3/7KFyAcZbIJcKYabAHN5jXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBAWoP%2FbtssUa8jRr3%2F7KFyAcZbIJcKYabAHN5jXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1898&quot; height=&quot;384&quot; data-origin-width=&quot;1898&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UA6af/btssMFfWNH3/PcrVtRheQMH7omxHULxKj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UA6af/btssMFfWNH3/PcrVtRheQMH7omxHULxKj1/img.png&quot; data-origin-width=&quot;1484&quot; data-origin-height=&quot;1554&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;54.69&quot; style=&quot;width: 54.056%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UA6af/btssMFfWNH3/PcrVtRheQMH7omxHULxKj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUA6af%2FbtssMFfWNH3%2FPcrVtRheQMH7omxHULxKj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1484&quot; height=&quot;1554&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b08hcO/btssVNdLOKS/99cZwpiwHgo1bUzvV0iDW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b08hcO/btssVNdLOKS/99cZwpiwHgo1bUzvV0iDW1/img.png&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;1934&quot; data-is-animation=&quot;false&quot; style=&quot;width: 44.7812%;&quot; data-widthpercent=&quot;45.31&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b08hcO/btssVNdLOKS/99cZwpiwHgo1bUzvV0iDW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb08hcO%2FbtssVNdLOKS%2F99cZwpiwHgo1bUzvV0iDW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1530&quot; height=&quot;1934&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2504&quot; data-origin-height=&quot;128&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S9Cv7/btssDNGjKYn/Xl1KKDpNm9J94QbFrAlhI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S9Cv7/btssDNGjKYn/Xl1KKDpNm9J94QbFrAlhI0/img.png&quot; data-alt=&quot;ACL을 변경하자 버킷 액세스가 퍼블릭으로 표시됩니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S9Cv7/btssDNGjKYn/Xl1KKDpNm9J94QbFrAlhI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS9Cv7%2FbtssDNGjKYn%2FXl1KKDpNm9J94QbFrAlhI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2504&quot; height=&quot;128&quot; data-origin-width=&quot;2504&quot; data-origin-height=&quot;128&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ACL을 변경하자 버킷 액세스가 퍼블릭으로 표시됩니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  모든 퍼블릭 액세스 차단 비활성 + 버킷&amp;nbsp;&lt;b&gt;&lt;b&gt;ACL 활성화&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  EC2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;(IAM 자격증명 X)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ACL 활성화 이전과 결과는 동일합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YeXiZ/btssVGTeiGK/VkDv6IkWT2LoaNaRebsn4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YeXiZ/btssVGTeiGK/VkDv6IkWT2LoaNaRebsn4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YeXiZ/btssVGTeiGK/VkDv6IkWT2LoaNaRebsn4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYeXiZ%2FbtssVGTeiGK%2FVkDv6IkWT2LoaNaRebsn4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;750&quot; height=&quot;41&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1808&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c79856/btssT7qcSHc/xKiND36vw3nvQEzIIcwukk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c79856/btssT7qcSHc/xKiND36vw3nvQEzIIcwukk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c79856/btssT7qcSHc/xKiND36vw3nvQEzIIcwukk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc79856%2FbtssT7qcSHc%2FxKiND36vw3nvQEzIIcwukk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;750&quot; height=&quot;48&quot; data-origin-width=&quot;1808&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;b&gt;  모든 퍼블릭 액세스 차단 비활성 + &lt;b&gt;&lt;b&gt;버킷 &lt;/b&gt;&lt;/b&gt;ACL 활성화 - &lt;span style=&quot;text-align: center;&quot;&gt;모든 사람(퍼블릭 액세스) 나열 허용&lt;/span&gt;&amp;nbsp;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  EC2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;(IAM 자격증명 X)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;모든 사람에게 나열 작업을 허용했기 때문에 서명이 없는 상태에서도 버킷의 객체 나열이&amp;nbsp; 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9bh1Y/btssAFWAhaG/MTvhTSBDmYYxC3xDIPdX7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9bh1Y/btssAFWAhaG/MTvhTSBDmYYxC3xDIPdX7K/img.png&quot; data-alt=&quot;ACL 변경 후 - 모든 사람(퍼블릭 액세스) 나열 허용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9bh1Y/btssAFWAhaG/MTvhTSBDmYYxC3xDIPdX7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9bh1Y%2FbtssAFWAhaG%2FMTvhTSBDmYYxC3xDIPdX7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;762&quot; height=&quot;78&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ACL 변경 후 - 모든 사람(퍼블릭 액세스) 나열 허용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;80&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcrTUi/btssNlBwebv/Xk5bCYUqeqCa8yM87dItd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcrTUi/btssNlBwebv/Xk5bCYUqeqCa8yM87dItd1/img.png&quot; data-alt=&quot;하지만 객체 다운로드는 불가능합니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcrTUi/btssNlBwebv/Xk5bCYUqeqCa8yM87dItd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcrTUi%2FbtssNlBwebv%2FXk5bCYUqeqCa8yM87dItd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;768&quot; height=&quot;42&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;80&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;하지만 객체 다운로드는 불가능합니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 객체 ACL&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 객체별 권한을 변경해보겠습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;memo1.txt &amp;rarr; 모든 사람(퍼블릭 액세스) 읽기 허용&lt;/li&gt;
&lt;li&gt;memo2.txt &amp;rarr; 인증된 사용자 그룹(AWS 계정이 있는 모든 사용자) 읽기 허용&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3yEPf/btssIpq6Euw/kaXaF9aNWZPkqG3RIZnj31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3yEPf/btssIpq6Euw/kaXaF9aNWZPkqG3RIZnj31/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1490&quot; data-origin-height=&quot;1596&quot; data-filename=&quot;img 19.png&quot; data-widthpercent=&quot;46.1&quot; style=&quot;width: 45.5601%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3yEPf/btssIpq6Euw/kaXaF9aNWZPkqG3RIZnj31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3yEPf%2FbtssIpq6Euw%2FkaXaF9aNWZPkqG3RIZnj31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1490&quot; height=&quot;1596&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mYlXK/btssNstOjXV/Motu5Ih9yZWrlT08tS6nO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mYlXK/btssNstOjXV/Motu5Ih9yZWrlT08tS6nO1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1476&quot; data-origin-height=&quot;1352&quot; data-filename=&quot;img 21.png&quot; style=&quot;width: 53.2771%;&quot; data-widthpercent=&quot;53.9&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mYlXK/btssNstOjXV/Motu5Ih9yZWrlT08tS6nO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmYlXK%2FbtssNstOjXV%2FMotu5Ih9yZWrlT08tS6nO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1476&quot; height=&quot;1352&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  모든 퍼블릭 액세스 차단 비활성 +&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;b&gt;버킷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;ACL 활성화&amp;nbsp;+ 객체 ACL &lt;b&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: center;&quot;&gt;모든 사람(퍼블릭 액세스) 읽기 허용&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  EC2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;(IAM 자격증명 X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;객체 수준에서 모든 사람에게 읽기를 허용하자 서명 없이도 객체 다운로드가 가능합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1438&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cR1gIU/btssHfWzuxi/oVTS2Ys4qazPGBakFKTLD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cR1gIU/btssHfWzuxi/oVTS2Ys4qazPGBakFKTLD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cR1gIU/btssHfWzuxi/oVTS2Ys4qazPGBakFKTLD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcR1gIU%2FbtssHfWzuxi%2FoVTS2Ys4qazPGBakFKTLD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;695&quot; height=&quot;38&quot; data-origin-width=&quot;1438&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  모든 퍼블릭 액세스 차단 비활성 +&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;b&gt;버킷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;ACL 활성화&amp;nbsp;+ 객체 ACL&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt; 인증된 사용자 그룹(AWS 계정이 있는 모든 사용자)&lt;/span&gt;&lt;span style=&quot;text-align: center;&quot;&gt;&amp;nbsp;읽기 허용&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  EC2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;(IAM 자격증명 X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;AWS 계정에서 객체에 읽기가 가능한 정책으로 AWS 계정이 아닐 경우 읽기 작업이 거부되어야합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1250&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eshDzx/btssPxi85Bn/s04EVMbOkzRO7gr3YpH9mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eshDzx/btssPxi85Bn/s04EVMbOkzRO7gr3YpH9mK/img.png&quot; data-alt=&quot;credential이 없다고 나옵니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eshDzx/btssPxi85Bn/s04EVMbOkzRO7gr3YpH9mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeshDzx%2FbtssPxi85Bn%2Fs04EVMbOkzRO7gr3YpH9mK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;711&quot; height=&quot;43&quot; data-origin-width=&quot;1250&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;credential이 없다고 나옵니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CIIki/btssVVJBdES/hakELzbKKcqbx84XQptDek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CIIki/btssVVJBdES/hakELzbKKcqbx84XQptDek/img.png&quot; data-alt=&quot;서명을 없애자 404 에러가 나타나며 파일이 존재하지 않는다고 표시됩니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CIIki/btssVVJBdES/hakELzbKKcqbx84XQptDek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCIIki%2FbtssVVJBdES%2FhakELzbKKcqbx84XQptDek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;721&quot; height=&quot;31&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서명을 없애자 404 에러가 나타나며 파일이 존재하지 않는다고 표시됩니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; ️ PC&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;(IAM 자격증명 O)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS 자격증명이 있는 로컬 PC에서는 어떨까요 ?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1464&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw5W0v/btssHg81dfd/FBpg2AhWK48ffAMoKKo85K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw5W0v/btssHg81dfd/FBpg2AhWK48ffAMoKKo85K/img.png&quot; data-alt=&quot;서명이 있는 상태에서는 AWS 계정임이 인증되기 때문에 다운로드가 이뤄집니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw5W0v/btssHg81dfd/FBpg2AhWK48ffAMoKKo85K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw5W0v%2FbtssHg81dfd%2FFBpg2AhWK48ffAMoKKo85K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;705&quot; height=&quot;59&quot; data-origin-width=&quot;1464&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서명이 있는 상태에서는 AWS 계정임이 인증되기 때문에 다운로드가 이뤄집니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r717c/btssSpLWX7c/kSB90xJTuKsvNIQxciEb9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r717c/btssSpLWX7c/kSB90xJTuKsvNIQxciEb9k/img.png&quot; data-alt=&quot;로컬 PC에서는 403에러가 발생합니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r717c/btssSpLWX7c/kSB90xJTuKsvNIQxciEb9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr717c%2FbtssSpLWX7c%2FkSB90xJTuKsvNIQxciEb9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;707&quot; height=&quot;60&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로컬 PC에서는 403에러가 발생합니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 버킷 정책 수정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 ACL 설정을 유지한 상태에서 버킷 정책을 수정해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 정책은 ahss-닉네임 버킷에 있는 객체들에 대한 GetObject 작업을 허용한다는 정책입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서 &lt;b&gt;Principal 필드는 리소스에 대한 액세스를 허용하거나 거부할 사람, 보안 주체를 지정&lt;/b&gt;합니다. 특정 AWS 계정, IAM 사용자, AWS 서비스 등이 주체가 될 수 있습니다. 다음 정책과 같이 Principal 필드에서 와일드카드 &quot;*&quot;를 사용하면 모든 보안 주체에 적용되어 익명의 사용자에게도 접근을 허용하게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
        {
            &quot;Sid&quot;: &quot;PublicReadGetObject&quot;,
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Principal&quot;: &quot;*&quot;,
            &quot;Action&quot;: &quot;s3:GetObject&quot;,
            &quot;Resource&quot;: &quot;arn:aws:s3:::ahss-닉네임/*&quot;
        }
    ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3 접근 제어는 제어에 관여하는 정책들이 많아 다소 복잡하게 느껴질 수 있습니다. AWS에서 &lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/what-is-access-analyzer.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IAM Access Analyzer&lt;/a&gt;라는 액세스 분석기를 제공하고 있으니 활용해보시면 좋을 것 같습니다.&amp;nbsp;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 실습 리소스 삭제&lt;/b&gt;&lt;/h2&gt;
&lt;pre class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 버킷에 객체 모두 삭제
aws s3 rm s3://ahss-$NICKNAME --recursive

# 실습에 사용한 S3 버킷 삭제
aws s3 rb s3://ahss-$NICKNAME

# 확인
aws s3 ls&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;2. S3 보안 강화&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3 보안 강화를 위한 AWS 공식 Workshop이나 자료들을 참고하여 S3 보안을 강화할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3의 기능 중 하나인 &lt;span data-token-index=&quot;0&quot;&gt;Pre-signed URL을 사용하여 임시적으로만 객체에 접근할 수 있게 하고,&lt;a href=&quot;https://catalog.us-east-1.prod.workshops.aws/workshops/74237958-77c8-4e7f-a02f-ae201a04d759/en-US/s3-security-best-practices-lab/02-securityexercises&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; Security Best Practice&lt;/a&gt;를 준수하도록 설정해보겠습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Pre-Signed URL 활성화&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pre-Signed URL을 사용하면 사용자가 AWS 계정이나 권한이 없어도, 버킷 정책 수정 없이 특정 객체에 대한 액세스가 가능하도록 설정할 수 있습니다. 통지서 같은 것들이 SMS로 수신됐을 때 특정 기간동안 링크만으로도 내 정보에 접근할 수 있는 경우가 있는데요, Pre- Signed URL을 사용하면 이런 작업이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소 &lt;span style=&quot;background-color: #ffffff; color: #16191f; text-align: start;&quot;&gt;1분에서 최대 7일까지 유효한 URL을 생성할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; ️ PC&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;(IAM 자격증명 O) 에서 다음 명령을 실행해보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1693642955237&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 버킷생성
aws s3 mb s3://ahss-$NICKNAME-presign --region ap-northeast-2

# 확인
aws s3 ls
aws s3api get-public-access-block --bucket ahss-$NICKNAME-presign | jq

# 그림파일 다운로드
curl https://www.nasa.gov/sites/default/files/thumbnails/image/main_image_star-forming_region_carina_nircam_final-5mb.jpg -o jameswebb.jpg

# S3로 업로드
aws s3 cp jameswebb.jpg s3://ahss-$NICKNAME-presign

# 파일 확인
aws s3 ls s3://ahss-$NICKNAME-presign --human-readable
aws s3api list-objects --bucket ahss-$NICKNAME-presign | jq&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pre-signed URL을 생성합니다. URL이 유효하게 지속될 시간을 --expires-in 옵션값으로 입력해줍니다. 600은 10분을 의미합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1693643256033&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws s3 presign s3://ahss-$NICKNAME-presign/jameswebb.jpg --expires-in 600&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1962&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uMVwG/btssVKuzYxf/NlptQtinkBbCUfVFeALnxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uMVwG/btssVKuzYxf/NlptQtinkBbCUfVFeALnxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uMVwG/btssVKuzYxf/NlptQtinkBbCUfVFeALnxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuMVwG%2FbtssVKuzYxf%2FNlptQtinkBbCUfVFeALnxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;782&quot; height=&quot;161&quot; data-origin-width=&quot;1962&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ 모든 퍼블릭 액세스 차단 활성화&lt;/b&gt; 상태이지만생성된 URL을 브라우저에 입력했더니 다음과 같이 객체가 표시되는 것을 확인할 수 있었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2636&quot; data-origin-height=&quot;1720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/do4dRQ/btssSEh4cxo/ULUleoZCfb1Z1fenoLd2y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/do4dRQ/btssSEh4cxo/ULUleoZCfb1Z1fenoLd2y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/do4dRQ/btssSEh4cxo/ULUleoZCfb1Z1fenoLd2y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdo4dRQ%2FbtssSEh4cxo%2FULUleoZCfb1Z1fenoLd2y1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;731&quot; height=&quot;477&quot; data-origin-width=&quot;2636&quot; data-origin-height=&quot;1720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Require HTTPS&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안전한 통신을 위해 HTTPS를 사용한 연결이 아니면 버킷에 접근이 불가능하도록 하는 정책을 설정합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1693644321002&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
	&quot;Id&quot;: &quot;S3-Security-Deny-unless-HTTPS&quot;,
	&quot;Version&quot;: &quot;2012-10-17&quot;,
	&quot;Statement&quot;: [{
		&quot;Action&quot;: &quot;s3:*&quot;,
		&quot;Effect&quot;: &quot;Deny&quot;,
		&quot;Principal&quot;: &quot;*&quot;,
		&quot;Resource&quot;: &quot;arn:aws:s3:::ahss-닉네임-presign/*&quot;,
		&quot;Condition&quot;: {
			&quot;Bool&quot;: {
				&quot;aws:SecureTransport&quot;: false
			}
		}
	}]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정책을 추가하고 http, https 로 객체를 호출해 보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1693644559127&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# object's metadata 정보 확인 : endpoint-url 옵션 설정 &amp;gt;&amp;gt; http? https? 확인
aws s3api head-object --bucket ahss-$NICKNAME-presign --key jameswebb.jpg --endpoint-url http://s3.ap-northeast-2.amazonaws.com
aws s3api head-object --bucket ahss-$NICKNAME-presign --key jameswebb.jpg --endpoint-url https://s3.ap-northeast-2.amazonaws.com&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ 모든 퍼블릭 액세스 차단 활성화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; ️ PC&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(IAM 자격증명 O)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2166&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PTBxp/btssNkq8eKJ/lxksPZBPr05wcMmsgSir00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PTBxp/btssNkq8eKJ/lxksPZBPr05wcMmsgSir00/img.png&quot; data-alt=&quot;https로 호출 시 403에러가 발생하지만 https로 호출시에는 요청이 정상적으로 처리됩니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PTBxp/btssNkq8eKJ/lxksPZBPr05wcMmsgSir00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPTBxp%2FbtssNkq8eKJ%2FlxksPZBPr05wcMmsgSir00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;721&quot; height=&quot;176&quot; data-origin-width=&quot;2166&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https로 호출 시 403에러가 발생하지만 https로 호출시에는 요청이 정상적으로 처리됩니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. SSE-KMS 암호화 사용&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷을 생성하면 기본 암호화가 SSE-S3(S3 관리 키)으로 구성되어 있습니다. SSE-KMS를 사용하도록 버킷 암호화 기본값을 업데이트하여 새 객체가 SSE-KMS(KMS 관리 키)를 사용하도록 설정합니다. 두 방식 모두 안전하지만 &lt;s&gt;&lt;i&gt;AWS의 IDC가 털려서 S3 키가 유출된다면...?&amp;nbsp; &lt;/i&gt;&lt;/s&gt;일반적으로 KMS 관리 키가 더 보안 수준이 높다고 간주됩니다.&amp;nbsp; &lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/replication-config-for-kms-objects.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;서버 측 암호화(SSE-C, SSE-S3, SSE-KMS, DSSE-KMS)를 사용하여 생성된 객체 복제&lt;/a&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #16191f; text-align: start;&quot;&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;1422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7DS5V/btssSnHm0H9/XHxKok6iFnzeIh4xvl05vK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7DS5V/btssSnHm0H9/XHxKok6iFnzeIh4xvl05vK/img.png&quot; data-alt=&quot;KMS 키 중에서 S3 키를 선택합니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7DS5V/btssSnHm0H9/XHxKok6iFnzeIh4xvl05vK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7DS5V%2FbtssSnHm0H9%2FXHxKok6iFnzeIh4xvl05vK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;660&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;1422&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;KMS 키 중에서 S3 키를 선택합니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;이렇게 설정된 상태에서 버킷에 객체를 업로드하면 ServerSideEncryption이 기본적으로 Kms로 설정됩니다.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;✅ 모든 퍼블릭 액세스 차단 활성화&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;&lt;b&gt; ️ PC&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(IAM 자격증명 O)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1693645631463&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 객체 업로드 
echo &quot;123456789abcdefg&quot; &amp;gt; textfile
aws s3api put-object --key text02 --body textfile --bucket ahss-$NICKNAME-presign

# object's metadata 정보 확인 : ServerSideEncryption 확인
aws s3api head-object --bucket ahss-$NICKNAME-presign --key text02 | jq&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1668&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pUqdI/btssSqD2W4S/xE9PpyPQQHcJTHUxlKqeA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pUqdI/btssSqD2W4S/xE9PpyPQQHcJTHUxlKqeA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pUqdI/btssSqD2W4S/xE9PpyPQQHcJTHUxlKqeA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpUqdI%2FbtssSqD2W4S%2FxE9PpyPQQHcJTHUxlKqeA0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;192&quot; data-origin-width=&quot;1668&quot; data-origin-height=&quot;442&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 응용해서 &lt;span data-token-index=&quot;0&quot;&gt;ServerSideEncryption&quot;: &quot;aws:kms&quot; 이 아닌 객체는 업로드 금지하도록 버킷 정책을 설정할 수도 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1693645760281&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
	&quot;Id&quot;: &quot;S3-Security-Deny-unless-SSE-KMS&quot;,
	&quot;Version&quot;: &quot;2012-10-17&quot;,
	&quot;Statement&quot;: [{
		&quot;Effect&quot;: &quot;Deny&quot;,
		&quot;Principal&quot;: &quot;*&quot;,
		&quot;Action&quot;: &quot;s3:PutObject&quot;,
		&quot;Resource&quot;: &quot;arn:aws:s3:::ahss-$NICKNAME-presign/*&quot;,
		&quot;Condition&quot;: {
			&quot;StringNotEquals&quot;: {
				&quot;s3:x-amz-server-side-encryption&quot;: &quot;aws:kms&quot;
			}
		}
	}]
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. AWS Config 규칙을 사용하여 퍼블릭 버킷 감지&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS Config는 리소스의 구성 및 관계에 대한 지속적인 진단, 감사 및 평가를 수행하는 서비스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 직접 규칙을 설정할 수도 있고, AWS에서 제공하는 관리형 규칙을 사용해 편리하게 감사 및 추적이 가능합니다. access key 관리 주기, acm 만료 일자 확인 등 리소스와 관련된 항목들을 규칙으로 설정해두고 이를 위반할 시 알림을 받도록 구성하여 리소스 관리에 대한 가시성을 높일 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3 bucket과 관련된 규칙도 제공하고 있는데요, 여기서 s3 bucket이 Public 상태가 될 경우를 추적하는 규칙을 추가해보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #16191f; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 23.png&quot; data-origin-width=&quot;1846&quot; data-origin-height=&quot;1198&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xQUAT/btssPv6L9dK/C20SEpuqkcQt3clywNRVRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xQUAT/btssPv6L9dK/C20SEpuqkcQt3clywNRVRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xQUAT/btssPv6L9dK/C20SEpuqkcQt3clywNRVRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxQUAT%2FbtssPv6L9dK%2FC20SEpuqkcQt3clywNRVRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;647&quot; height=&quot;420&quot; data-filename=&quot;img 23.png&quot; data-origin-width=&quot;1846&quot; data-origin-height=&quot;1198&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;규칙을 추가해두면 위반된 리소스를 탐지하고 내용을 표시해줍니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2306&quot; data-origin-height=&quot;1344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQN0nj/btssUagdFWF/HF6d4HUu0yaHoOojnaatbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQN0nj/btssUagdFWF/HF6d4HUu0yaHoOojnaatbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQN0nj/btssUagdFWF/HF6d4HUu0yaHoOojnaatbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQN0nj%2FbtssUagdFWF%2FHF6d4HUu0yaHoOojnaatbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;651&quot; height=&quot;379&quot; data-origin-width=&quot;2306&quot; data-origin-height=&quot;1344&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Config 위반 알림이 발생 시 Slack으로 알람을 받도록 설정해두면 매번 콘솔에서 확인하지 않아도 쉽게 리소스 변경 추적이 가능하겠죠 ?&amp;nbsp;&amp;nbsp;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3는 자주 사용하지만 보통 로그 저장용으로 사용하여 완전히 프라이빗하게 구성해서 사용하고 있어 세분화된 제어를 해보지는 않았었습니다. S3와 권한 문제는 알면 알수록 복잡하고, 테스트해 볼 경우의 수가 무궁무진하다고 느꼈습니다. EC2에서는 404가, PC에서는 403에러가 발생하는 이유에 대해서도 다뤄보려 합니다. 아직 부족한 부분이 많지만 첫걸음을 뗐다고 생각하면서 차근차근 공부해보겠습니다. :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;CloudNet@팀의 AHSS(AWS Hacking &amp;amp; Security 스터디) 학습 내용과 제가 공부한 내용을 정리한 글입니다. 더 좋은 방법이나 틀린 내용이 있으면 말씀해주세요 :)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;&lt;b&gt;참고 자료&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=zIZ6_tYujts&quot;&gt;Builders Online - AWS IAM과 친해지기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/access-control-overview.html#access-control-resources-manage-permissions-basics%20&quot;&gt;S3 사용 설명서: 리소스 액세스 관리&lt;/a&gt;&lt;/p&gt;</description>
      <category>☁️ AWS</category>
      <category>AWS</category>
      <category>s3</category>
      <category>Security</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/24</guid>
      <comments>https://chnh.tistory.com/24#entry24comment</comments>
      <pubDate>Sat, 2 Sep 2023 18:31:43 +0900</pubDate>
    </item>
    <item>
      <title>Terraform 코드 네이밍 컨벤션</title>
      <link>https://chnh.tistory.com/22</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 잘 사용하고 있는 분들이 많겠지만, 개인적으로 한번쯤 정리해보고 싶었던 부분이라 글을 작성하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스를 생성하든, 함수를 생성하든 나에게 이름을 짓는 순간은 가장 심혈을 기울이게 되는 순간 중 하나이다. 미래의 나를 위한 가독성, 협업을 위해서, 유지 보수, 오류 감소, 문서로서의 역할 등등... 네이밍 컨벤션이 중요한 이유는 넘친다. IaC 도입의 긍정적인 효과&amp;mdash;공동작업과 재사용성, 기술의 자산화 등&amp;mdash;을 온전히 누리기 위해서는 네이밍 컨벤션에 대한 협의가 반드시 이루어져야한다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 하면 '좋은' 인프라를 위한 네이밍을 할 수 있을지 Best Practice를 기반으로 정리하였다. 주관적인 견해와 수집한 정보들을 바탕으로 작성한 것이므로 다음 내용이 정답이 아님을 미리 밝힌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Terraform 코드 네이밍 컨벤션&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제목을 입력해주세요_-001.png&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bimanS/btsnvZcH194/kkZgF2SU1iYqjTf3eK94P0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bimanS/btsnvZcH194/kkZgF2SU1iYqjTf3eK94P0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bimanS/btsnvZcH194/kkZgF2SU1iYqjTf3eK94P0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbimanS%2FbtsnvZcH194%2FkkZgF2SU1iYqjTf3eK94P0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;566&quot; height=&quot;318&quot; data-filename=&quot;제목을 입력해주세요_-001.png&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;540&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 자원 이름에 &lt;code&gt;-&lt;/code&gt;(dash)대신 &lt;code&gt;_&lt;/code&gt;(underscore) 사용&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS 콘솔에서 리소스를 생성할 때는 주로 -를 사용한 케밥케이스(e.g. prd-crm-web-ec2)를 사용하여 리소스를 생성했는데 ...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테라폼 공식 문서에 있는 예제들도 주로 스네이크 케이스를 사용하고 있다&lt;b&gt;.&lt;/b&gt; &lt;b&gt;리소스 이름, 데이터 소스 이름, 변수 이름, 출력 등 모든 곳에서 _를 사용하는 것이 좋다고 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-는 테라폼에서 뺄셈이나 요소 제거등에 사용될 수 있기 때문이다. -를 연산자로 사용하는 경우 자원 이름에도 -를 사용했을 때 오류가 발생할 잠재적인 위험이 있기 때문에 자원 이름에 - 사용을 지양한다고.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;그리고 이건 개인적으로 느낀 장점인데, _를 쓰면 해당 어구를 더블클릭했을 때 전체 선택이 된다. private_nat 는 더블클릭하면 한번에 선택되지만 private-nat는 그렇지 않다. _를 쓰면 여러 블럭을 한번에 수정할때 편해진다.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ Do&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;resource &quot;aws_eks_cluster&quot; &quot;my_cluster&quot; {}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❌ Do Not&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;resource &quot;aws_eks_cluster&quot; &quot;my-cluster&quot; {}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 소문자 사용&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가독성 향상을 위해 소문자를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 중복 최소화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스 유형(type)을 리소스 이름(name)에 반복하는 것을 지양한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중복을 방지하고 이름을 간결하게 유지해서 리소스의 용도를 명확하게 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테라폼은 다음과 같은 구조로 작성되는데,&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;BLOCK TYPE&amp;gt; &quot;&amp;lt;BLOCK LABEL&amp;gt;&quot; &quot;&amp;lt;BLOCK LABEL&amp;gt;&quot; {
  &amp;lt;IDENTIFIER&amp;gt; = &amp;lt;EXPRESSION&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록 타입이 resource라고 가정했을 때 다음과 같은 구조를 갖게 된다.&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;resource &quot;&amp;lt;PROVIDER&amp;gt;_&amp;lt;TYPE&amp;gt;&quot; &quot;&amp;lt;NAME&amp;gt;&quot; {
  # Block contents
  argument_1 = &quot;value&quot;
  argument_2 = &quot;value&quot;

  # Nested Block
  nested_block {
    # Block contents
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &quot;&quot; 부분의 이 리소스 명칭이다. AWS의 라우팅 테이블을 생성한다면 &quot;aws_route_table&quot;과 같이 표기한다. 이때 뒤에 오는 &quot;&quot;에 aws, route_table과 반복을 피하는 것을 권고한다. 대신 용도를 구분할 수 있도록 public, private 등의 명칭만 표기하는 것을 추천한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ Do&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;resource &quot;aws_route_table&quot; &quot;public&quot; {}
resource &quot;aws_vpc_endpoint&quot; &quot;apigateway&quot; {}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❌ Do Not&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;resource &quot;aws_route_table&quot; &quot;public_route_table&quot; {}
resource &quot;aws_vpc_endpoint&quot; &quot;apigateway_endpoint&quot; {}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 이름에는 기본적으로 단수 명사를 사용한다.&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, 여러 값을 포함하게 되는 경우&amp;mdash;variable 블록에서 &lt;code&gt;list(...)&lt;/code&gt; or &lt;code&gt;map(...)&lt;/code&gt;를 사용하거나 output 블록에서 &lt;b&gt;반환되는 값이 복수형인 경우&lt;/b&gt; 등&amp;mdash;에는 복수형으로 표기한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ Do&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ceylon&quot;&gt;&lt;code&gt;output &quot;rds_instance_endpoint&quot; {
  description = &quot;An instance endpoint&quot;
  value       = aws_rds_cluster_instance.this.endpoint
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;output &quot;rds_cluster_instance_endpoints&quot; {
  description = &quot;A list of all cluster instance endpoints&quot;
  value       = aws_rds_cluster_instance.this.*.endpoint
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❌ Do Not&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ceylon&quot;&gt;&lt;code&gt;output &quot;rds_instance_endpoints&quot; {
  description = &quot;An instance endpoint&quot;
  value       = aws_rds_cluster_instance.this.endpoint
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. tag는 마지막에&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, &lt;code&gt;depends_on&lt;/code&gt;이나 &lt;code&gt;lifecycle&lt;/code&gt; 인자는 tag 보다 뒤에 명시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ Do&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;resource &quot;aws_nat_gateway&quot; &quot;this&quot; {
  count = 2

  allocation_id = &quot;...&quot;
  subnet_id     = &quot;...&quot;

  tags = {
    Name = &quot;...&quot;
  }

  depends_on = [aws_internet_gateway.this]

  lifecycle {
    create_before_destroy = true
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❌ Do Not&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;resource &quot;aws_nat_gateway&quot; &quot;this&quot; {
  count = 2

  tags = &quot;...&quot;

  depends_on = [aws_internet_gateway.this]

  lifecycle {
    create_before_destroy = true
  }

  allocation_id = &quot;...&quot;
  subnet_id     = &quot;...&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. variable block 안에 들어가는 key 값들을 어떻게 정렬할지 미리 설정하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;e.g. description , type, default, validation&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;7. Output의 이름은 {name}_{type}_{attribute} 구조로&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;{name}&lt;/code&gt;은 provider 접두사가 없는 리소스 또는 데이터 소스 이름&lt;br /&gt;aws_subnet &amp;rarr; {name}은 subnet&lt;br /&gt;aws_vpc &amp;rarr; {name}은 vpc이다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{type}&lt;/code&gt;은 리소스 소스의 유형&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{attribute}&lt;/code&gt;은 출력에서 반환되는 속성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ Do&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;output &quot;security_group_id&quot; {
  description = &quot;The ID of the security group&quot;
  value       = &quot;&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❌ Do Not&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;output &quot;this_security_group_id&quot; {
  description = &quot;The ID of the security group&quot;
  value       = element(concat(coalescelist(aws_security_group.this.*.id, aws_security_group.web.*.id), [&quot;&quot;]), 0)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고) 네이밍 외에 스타일 컨벤션과 관련된 부분은 다음 명령어로 해결할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;terraform fmt&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;막상 이렇게 정리해보니까 내가 지키지 않고 있는 규칙들도 있어서 (특히 리소스 타입과 이름을 중복하는 것) 차근차근 수정해나가야겠다. 이렇게 사용하다가 불편함이 생기면 또 업데이트 해보겠습니다 !&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;참고자료&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.terraform-best-practices.com/&quot;&gt;https://www.terraform-best-practices.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.hashicorp.com/terraform/language/expressions/references#named-values-and-dependencies&quot;&gt;https://developer.hashicorp.com/terraform/language/expressions/references#named-values-and-dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>  Terraform</category>
      <category>naming_convention</category>
      <category>Terraform</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/22</guid>
      <comments>https://chnh.tistory.com/22#entry22comment</comments>
      <pubDate>Thu, 13 Jul 2023 14:20:46 +0900</pubDate>
    </item>
    <item>
      <title>Golden Image Pipeline 구성 - 2. GitHub Actions로 이미지 생성 자동화</title>
      <link>https://chnh.tistory.com/21</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://chnh.tistory.com/20&quot;&gt;Golden Image Pipeline 구성 - 1. Packer와 Ansible로 이미지 만들기&lt;/a&gt;의  후속이다. 이번에는 golden ami를 정의한 packer 템플릿이나 ansible playbook에 변경 후  branch에 push될 경우 ami를 생성하도록 구성하는 방법을 설명한다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AMI ID를 콘솔에 접속하지 않고 바로 출력할 수 있도록 packer 템플릿에 manifest file을 생성하는 post-processor를 추가하고, 최신 linux ami를 가져오는 data 블럭을 새로 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1687763477747&quot; class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# base-linux-ami.pkr.hcl

locals {
  timestamp = regex_replace(timestamp(), &quot;[- TZ:]&quot;, &quot;&quot;)
}


data &quot;amazon-ami&quot; &quot;amzn2-lts&quot; {
  filters = {
    name                = &quot;amzn2-ami-hvm-*-x86_64-gp2&quot;
    root-device-type    = &quot;ebs&quot;
    virtualization-type = &quot;hvm&quot;
  }
  most_recent = true
  owners      = [&quot;amazon&quot;]
}


source &quot;amazon-ebs&quot; &quot;base-linux-ami&quot; {
  region        = &quot;ap-northeast-2&quot;
  ami_name      = &quot;amzn2-base-ami-${local.timestamp}&quot;
  source_ami    = data.amazon-ami.amzn2-lts.id
  vpc_id        = &quot;vpc-id&quot;
  subnet_id     = &quot;subnet-id&quot;
  instance_type = &quot;t2.micro&quot;
  ssh_username  = &quot;ec2-user&quot;
  tags = {
    Name          = &quot;amzn2-base-ami-${local.timestamp}&quot;
    Base_AMI_ID   = &quot;{{ .SourceAMI }}&quot;
    Base_AMI_Name = &quot;{{ .SourceAMIName }}&quot;
  }
}


build {
  sources = [
    &quot;source.amazon-ebs.base-linux-ami&quot;
  ]

  provisioner &quot;ansible&quot; {
    playbook_file = &quot;playbook/playbook.yml&quot;
    use_proxy     = &quot;false&quot;
    user          = &quot;ec2-user&quot;
  }

  post-processor &quot;manifest&quot; {
    output     = &quot;manifest.json&quot;
    strip_path = true
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Github Actions Secret 설정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Github Actions이 AWS와 상호 작용하기 위해 자격 증명 구성이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Github Actions는 CI/CD 워크플로에서 중요 데이터나 암호들을 안전하게 사용할 수 있도록 Secrets를 제공하고 있다. 여기에 액세스 키를 저장하면 Github 실행 로그에도 마스킹 처리가 되고, 정의된 컨텍스트 내에서만 사용할 수 있기 때문에 사용 범위 제한이 가능하다. AWS에서 해당 액세스 키의 주체에게 최소 권한만을 부여하고, 자주 액세스키를 교체해주는 등의 작업을 통해 보다 안전하게 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Golden image pipeline을 구성할 리포지토리의 Settings 탭에서 Secrets 메뉴에 접근할 수 있다. 다음 두 key에 대한 값을 저장한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS_ACCESS_KEY_ID&lt;/li&gt;
&lt;li&gt;AWS_SECRETE_ACCESS_KEY_ID&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 8.png&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;735&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8Maxv/btsljgI2BeJ/w51ztq0xQPnKYXkePQBEx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8Maxv/btsljgI2BeJ/w51ztq0xQPnKYXkePQBEx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8Maxv/btsljgI2BeJ/w51ztq0xQPnKYXkePQBEx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8Maxv%2FbtsljgI2BeJ%2Fw51ztq0xQPnKYXkePQBEx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1207&quot; height=&quot;735&quot; data-filename=&quot;img 8.png&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;735&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 설정한 자격 증명은 이후&lt;b&gt; workflow 파일에서 AWS 자격증명을 구성하는 데에 사용된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 9.png&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cz3QzM/btsluUYILYo/PJ84RxYUEMP68UVgPUWrVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cz3QzM/btsluUYILYo/PJ84RxYUEMP68UVgPUWrVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cz3QzM/btsluUYILYo/PJ84RxYUEMP68UVgPUWrVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcz3QzM%2FbtsluUYILYo%2FPJ84RxYUEMP68UVgPUWrVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;818&quot; height=&quot;450&quot; data-filename=&quot;img 9.png&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Github Actions workflow 구성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;workflow 파일 작성 문법에 대한 글은 다음 게시글을 참고 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://chnh.tistory.com/19&quot;&gt;GitHub Actions Workflow 문법 정리&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 내가 작성한 workflow 정의 파일이다. workflow 파일은 &lt;code&gt;.github/workflows&lt;/code&gt; 아래에 위치해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main branch에 push 작업이 일어날 때마다 jobs 아래에 정의된 작업들이 순차적으로 실행된다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;#build-ami.yml

name: Build Golden Image

on:
  push:
    branches:
      - main
jobs:
  packer:
    runs-on: ubuntu-latest
    name: Run Packer
    steps:
      - name: Checkout Repository # 현재 리포지토리의 코드를 체크아웃
        uses: actions/checkout@v2

      - name: Configure AWS Credentials #  GitHub Secrets에서 AWS 자격 증명을 구성
        uses: aws-actions/configure-aws-credentials@v1
        with: 
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

      - name: Initialize Packer Template # Packer 템플릿 초기화
        uses: hashicorp/packer-github-actions@master
        with:
          command: init

      - name: Validate Packer template # Packer 템플릿 유효성 검증 
        run: packer validate base-linux-ami.pkr.hcl

      - name: Build AMI # Packer 템플릿 build
        run: packer build base-linux-ami.pkr.hcl
        env:
          PACKER_LOG: 1 # Packer 로그 활성화&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Github Repository로 push&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;workflow 정의파일을 업로드한 다음, ansible playbook 파일을 수정 후 main branch에 push해보겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DlCVS/btsluWPHs1W/iFRscb5nBf7jXEeNoIqkuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DlCVS/btsluWPHs1W/iFRscb5nBf7jXEeNoIqkuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DlCVS/btsluWPHs1W/iFRscb5nBf7jXEeNoIqkuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDlCVS%2FbtsluWPHs1W%2FiFRscb5nBf7jXEeNoIqkuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;609&quot; height=&quot;205&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;push 명령어 실행 후 바로 Github Actions이 실행된다. commit message와 함께 작업 내용이 표시되고, 실시간으로 작업 진행 현황을 확인할 수 있다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;75&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x0Xmo/btslt2bYn2q/a0JqtpJl2lAKg9ZrfvbMaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x0Xmo/btslt2bYn2q/a0JqtpJl2lAKg9ZrfvbMaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x0Xmo/btslt2bYn2q/a0JqtpJl2lAKg9ZrfvbMaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx0Xmo%2Fbtslt2bYn2q%2Fa0JqtpJl2lAKg9ZrfvbMaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;606&quot; height=&quot;75&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;75&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJUlIg/btsltjEZUxu/4jl6S7YLhio9l7uoGYJuv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJUlIg/btsltjEZUxu/4jl6S7YLhio9l7uoGYJuv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJUlIg/btsltjEZUxu/4jl6S7YLhio9l7uoGYJuv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJUlIg%2FbtsltjEZUxu%2F4jl6S7YLhio9l7uoGYJuv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;593&quot; height=&quot;320&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업이 정상적으로 완료되면 Github UI 상에서는 다음과 같이 표시된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjTxv5/btsljiGXdb9/nQUrBb1Yk0nePfobM2Ojzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjTxv5/btsljiGXdb9/nQUrBb1Yk0nePfobM2Ojzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjTxv5/btsljiGXdb9/nQUrBb1Yk0nePfobM2Ojzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjTxv5%2FbtsljiGXdb9%2FnQUrBb1Yk0nePfobM2Ojzk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;588&quot; height=&quot;337&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;post-processor가 생성한 manifest 파일에는 ami id와 packer run uuid 정보 등이 표시된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 11.png&quot; data-origin-width=&quot;776&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKP2E6/btsls6yORn0/sZHPbAXS0lukPXLWXmT5UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKP2E6/btsls6yORn0/sZHPbAXS0lukPXLWXmT5UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKP2E6/btsls6yORn0/sZHPbAXS0lukPXLWXmT5UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKP2E6%2Fbtsls6yORn0%2FsZHPbAXS0lukPXLWXmT5UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;550&quot; height=&quot;227&quot; data-filename=&quot;img 11.png&quot; data-origin-width=&quot;776&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 스크립트를 실행하여 manifest 파일에서 최신 ami id를 불러와봤다. AMI ID가 잘 출력되는 걸 확인할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1687763281269&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# get_ami_id.sh

AMI_ID=$(jq -r '.builds[-1].artifact_id' manifest.json | cut -d &quot;:&quot; -f2)
echo $AMI_ID&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;508&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/78o2y/btsluVceuFW/2ZmKb5XbC9KxiyAHkVOGZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/78o2y/btsluVceuFW/2ZmKb5XbC9KxiyAHkVOGZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/78o2y/btsluVceuFW/2ZmKb5XbC9KxiyAHkVOGZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F78o2y%2FbtsluVceuFW%2F2ZmKb5XbC9KxiyAHkVOGZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;508&quot; height=&quot;37&quot; data-origin-width=&quot;508&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;figure data-ke-type=&quot;image&quot; data-ke-style=&quot;alignCenter&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;br /&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;참고자료&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.hashicorp.com/packer/tutorials/cloud-production/github-actions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.hashicorp.com/packer/tutorials/cloud-production/github-actions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>  CICD</category>
      <category>automate packer</category>
      <category>cicd</category>
      <category>devops</category>
      <category>GitHub Actions</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/21</guid>
      <comments>https://chnh.tistory.com/21#entry21comment</comments>
      <pubDate>Mon, 26 Jun 2023 16:13:42 +0900</pubDate>
    </item>
    <item>
      <title>Golden Image Pipeline 구성 - 1. Packer와 Ansible로 이미지 만들기</title>
      <link>https://chnh.tistory.com/20</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 Immutable Infrastructure가 무엇인지 이해하고, 이를 구현하기 위한 첫 단계로 Packer와 Ansible을 사용하여 골든 이미지를 만든다. 이후 Github Actions을 사용해 변경사항이 Ansible Playbook에 푸시될 때마다 자동으로 Packer를 실행하는 Golden Image 파이프라인을 구성한 다음, Terraform을 사용하여 변경된 이미지로 인프라를 교체하도록 설정하여 자동화된 Immutable Infra를 구현하는 것을 목표로 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성하면 요런느낌 ✨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;golden ami.drawio.png&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boMbJo/btslaSWse4G/c4TGxKBzCBFtuurFVNVdO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boMbJo/btslaSWse4G/c4TGxKBzCBFtuurFVNVdO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boMbJo/btslaSWse4G/c4TGxKBzCBFtuurFVNVdO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboMbJo%2FbtslaSWse4G%2Fc4TGxKBzCBFtuurFVNVdO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;881&quot; height=&quot;471&quot; data-filename=&quot;golden ami.drawio.png&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;471&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시리즈는 다음과 같이 계획되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Packer와 Ansible로 이미지 만들기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. GitHub Actions로 이미지 생성 자동화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Terraform을 사용하여 AWS에 변경된 인프라 배포&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Immutable Infrastructure와 Golden Image&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS를 사용중인 사람이라면 인스턴스를 생성할 때 AMI(Amazon Machine Image)를 사용해봤을 것이다. AMI는 미리 구성된 운영 체제와 설치된 소프트웨어를 포함하고 있는 머신 이미지인데, 덕분에 인스턴스를 시작할 때마다 수동으로 구성하는 절차 없이 빠르게 리소스를 프로비저닝 할 수 있다. 이 AMI에 대한 일종의 마스터 템플릿을 골든 이미지라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DevOps 관점에서 이미지, 특히 골든 이미지는 변경 불가능한 인프라(&lt;i&gt;&lt;a href=&quot;https://medium.com/the-cloud-architect/immutable-infrastructure-21f6613e7a23&quot;&gt;Immutable Infrastructure&lt;/a&gt;&lt;/i&gt;)를 구현하는 데 중요한 역할을 한다. 필요한 구성과 소프트웨어가 모두 포함된 완벽한 골든 이미지를 생성한 다음 해당 이미지를 사용하여 인프라를 생성한다는 아이디어로, 서버에 업데이트 또는 수정이 필요한 경우 이미 사용 중인 서버를 업데이트하는 대신 새로운 이미지를 사용하여 새 서버를 배포하는 방식을 선택한다. 즉 한번 실행된 인스턴스는 변경되지 않고, 변경이 필요한 경우에는 업데이트된 이미지를 가지고 아예 새로운 인스턴스로 교체한다. 때문에 구성 드리프트가 발생할 틈이 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-25-553x600.png&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SRHal/btsj0dsjXK1/EWK7gBLcs8L440ATeUfsT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SRHal/btsj0dsjXK1/EWK7gBLcs8L440ATeUfsT0/img.png&quot; data-alt=&quot;https://devopscube.com/immutable-infrastructure&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SRHal/btsj0dsjXK1/EWK7gBLcs8L440ATeUfsT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSRHal%2Fbtsj0dsjXK1%2FEWK7gBLcs8L440ATeUfsT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;553&quot; height=&quot;600&quot; data-filename=&quot;image-25-553x600.png&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://devopscube.com/immutable-infrastructure&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 인프라를 관리하면 다음과 같은 이점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;일관성&lt;/b&gt;: 모든 인스턴스가 동일하므로 구성 드리프트로 인해 문제가 발생할 가능성이 줄어든다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;효율성&lt;/b&gt;: 골든 이미지에는 OS뿐만 아니라 설치 및 구성된 애플리케이션도 포함될 수 있기 때문에 빠르게 부팅할 수  있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;신뢰성&lt;/b&gt;:  사전에 검증된 이미지를 사용하기때문에 구성 오류가 발생할 가능성이 크게 줄어든다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;확장성&lt;/b&gt;: 확장이 필요할 때 골든 이미지를 사용하여 새로운 동일한 인스턴스를 신속하게 온라인으로 가져올 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;복구 용이성&lt;/b&gt;: 새 버전에 문제가 있는 경우 이전 골든 이미지를 인스턴스화하여 이전 버전으로 쉽게 되돌릴 수 있고 현재 사용중인 서비스에 문제가 발생하는 경우 빠르게 복원할 수 있다.&lt;/li&gt;
&lt;li&gt;IaC의 발전이 Immutable Infra를 구현하는 데에 큰 기여를 했다고 생각한다. 이미지, 인스턴스, 네트워크와 같은 리소스들을 코드로 쫙 작성해서 한번에 테스트하고 승격하고 배포할 수 있게 됐으니 말이다. IaC가 등장하지 않았다면 일관된 방식으로 이런 단계를 반복하는 것은 많은 시간을 들이고, 구현한다 한들 수작업 과정에서 문제가 발생했겠지. ㅎㅎ...끔찍하다... 무튼 ! 이제 이 좋은 도구들을 가지고 자동으로 일관된 환경을 유지해보자.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Packer와 Ansible&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Packer_PrimaryLogo_Color_RGB.png&quot; data-origin-width=&quot;2376&quot; data-origin-height=&quot;1056&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2lGQE/btsjYtIRsES/yEDT8CbgYnQKtYJZwyRylK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2lGQE/btsjYtIRsES/yEDT8CbgYnQKtYJZwyRylK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2lGQE/btsjYtIRsES/yEDT8CbgYnQKtYJZwyRylK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2lGQE%2FbtsjYtIRsES%2FyEDT8CbgYnQKtYJZwyRylK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;403&quot; height=&quot;179&quot; data-filename=&quot;Packer_PrimaryLogo_Color_RGB.png&quot; data-origin-width=&quot;2376&quot; data-origin-height=&quot;1056&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Packer&lt;/b&gt;를 한 마디로 정의하자면 '&lt;b&gt;머신 이미지 빌더&lt;/b&gt;'라고 할 수 있을 것 같다&lt;b&gt;. Template&lt;/b&gt;을 사용해 여러 플랫폼의 머신 이미지를 생성할 수 있는 Hashicorp의 오픈소스로, AWS Image builder와 유사한 기능을 한다. Packer는 이미지를 만들 때 가상 머신의 특정 시점의 상태만을 저장하는 것이 아니라 이미지가 생성되는 과정도 코드로 저장되기 때문에 유사한 이미지를 반복 생성할 때 도움이 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Template 은 빌드하려는 이미지와 빌드 방법을 정의한 구성파일로, Builder와 Provisioner를 조합하여 구성한다. 초기에는 JSON 형식(.pkr.json)으로 템플릿을 작성했으나 현재는 Terraform과 같은 HCL2를 사용하도록 장려하고 있다. 이 글에서는 HCL로 템플릿을 작성한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;NV48K6U.png&quot; data-origin-width=&quot;938&quot; data-origin-height=&quot;470&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lektB/btslgiT4FVk/rM0RBAqBdnyC90ooEr9Nz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lektB/btslgiT4FVk/rM0RBAqBdnyC90ooEr9Nz1/img.png&quot; data-alt=&quot;https://hackmd.io/@XeusNguyen/BJtEoB_Ci&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lektB/btslgiT4FVk/rM0RBAqBdnyC90ooEr9Nz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlektB%2FbtslgiT4FVk%2FrM0RBAqBdnyC90ooEr9Nz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;758&quot; height=&quot;380&quot; data-filename=&quot;NV48K6U.png&quot; data-origin-width=&quot;938&quot; data-origin-height=&quot;470&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://hackmd.io/@XeusNguyen/BJtEoB_Ci&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Builder&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빌더는 머신을 생성하고 해당 머신에서 다양한 플랫폼용 이미지를 생성한다. AWS에서 사용할 AMI를 생성할지, Docker 컨테이너 이미지를 생성할지 등을 결 정한다.&lt;/li&gt;
&lt;li&gt;예시를 살펴보면 좀 더 감이 오는데, 다음은 일반적으로 사용하는 빌더들이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Amazon EC2 (amazon-ebs, amazon-ebssurrogate, amazon-ebsvolume, amazon-chroot, amazon-instance)&lt;/li&gt;
&lt;li&gt;Google Compute Engine(googlecompute)&lt;/li&gt;
&lt;li&gt;Azure Resource Manager(azure-arm)&lt;/li&gt;
&lt;li&gt;Docker (docker)&lt;/li&gt;
&lt;li&gt;VMWare(vmware-iso, vmware-vmx)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이외에도 custom builder나 packer 커뮤니티에서 지원하는 빌더를 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Provisioner&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로비저너는 built-in 또는 third-party 소프트웨어를 사용하여 부팅 후 패키지 설치, 커널 패치, 사용자 생성, 애플리케이션 코드 다운로드 등의 작업을 수행하여 이미지를 원하는 상태로 프로비저닝한다.&lt;/li&gt;
&lt;li&gt;다음과 같은 프로비저너들을 사용할 수 있으며, 최신 정보는 &lt;a href=&quot;https://developer.hashicorp.com/packer/plugins&quot;&gt;공식 문서&lt;/a&gt;에서 확인할 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.hashicorp.com/packer/plugins/provisioners/ansible/ansible&quot;&gt;ansible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ansible-local&lt;/li&gt;
&lt;li&gt;chef-client&lt;/li&gt;
&lt;li&gt;chef-solo&lt;/li&gt;
&lt;li&gt;file&lt;/li&gt;
&lt;li&gt;powershell&lt;/li&gt;
&lt;li&gt; shell&lt;/li&gt;
&lt;li&gt;shell-local&lt;/li&gt;
&lt;li&gt;puppet-masterless&lt;/li&gt;
&lt;li&gt;puppet-server&lt;/li&gt;
&lt;li&gt;salt-masterless&lt;/li&gt;
&lt;li&gt;windows-restart&lt;/li&gt;
&lt;li&gt;windows-shell&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Post-Processor&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;포스트 프로세서는 빌 드와 프로비저닝 후에 실행된다. 따라서 필수적인 옵션은 아니며, 프로비저닝 이후 생성된 artifact들에 대해 작업을 수행한다. 예를 들어 포트스 프로세서로 compress 를 사용하여 build된 이미지를 tar 파일로 압축해서 저장하거나, docker-push를 사용해 docker 레지스트리에 이미지를 푸시할 수 있다. manifest를 사용하여 artifact에 대한 정보를 json 파일로 출력하는 등의 작업 또한 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Ansible_logo.svg&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;315&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qJw1F/btskAHfIQDB/KGeXNqGJRu0MCWcDKqkQvk/tfile.svg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qJw1F/btskAHfIQDB/KGeXNqGJRu0MCWcDKqkQvk/tfile.svg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qJw1F/btskAHfIQDB/KGeXNqGJRu0MCWcDKqkQvk/tfile.svg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqJw1F%2FbtskAHfIQDB%2FKGeXNqGJRu0MCWcDKqkQvk%2Ftfile.svg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;134&quot; height=&quot;165&quot; data-filename=&quot;Ansible_logo.svg&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;315&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Ansible&lt;/b&gt;은 원격으로 서버를 구성하고 관리할 수 있는 RedHat의 오픈소스이다. Ansible은 Python을 기반으로 개발되었으며, YAML 포&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맷을 기반으로 인프라를 정의한다. Ansible을 사용하면 관리할 서버에 별도의 데몬을 설치하지 않고 원격으로 접속해서 서버를 구성할 수 있다. Packer로 이미지를 빌드할 때 Ansible을 프로비저너로 사용하면 이미지에 필요한 모든 소프트웨어를 사전에 설치할 수 있고, playbook을 작성해 여러번 재사용할 수 있어 효율적인 인프라 관리가 가능하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Packer, Ansible 설치&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;macOS를 사용중이라 brew로 설치했다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# install packer 
brew tap hashicorp/tap
brew install hashicorp/tap/packer

# install ansible
brew install ansible&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Ansible playbook 작성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;provisioner로 ansible을 사용할 것이기 때문에 playbook을 미리 작성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;playbook은 원격 host에서 실행할 일련의 작업을 yaml로 작성한 스크립트이다. 다음 스크립트는 ec2의 timezone을 서울로 변경하고, 최신 버전으로 git을 설치하고, 특정 버전의 nginx를 설치하고, nginx를 시작한다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# playbook.yml
- name: Start Playbook
  hosts: all
  become: yes
  tasks:
    - name: Set Asia/Seoul timezone
      timezone:
        name: Asia/Seoul

    - name: Install git
      yum:
        name: git
        state: latest

    - name: Enable extras
      command: amazon-linux-extras install -y nginx1.12
      args:
        creates: /etc/nginx/nginx.conf

    - name: Start Nginx
      ansible.builtin.systemd:
        name: nginx
        state: started
        enabled: yes&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. Packer 템플릿 생성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. packer 템플릿을 저장할 디렉토리를 생성한다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;mkdir packer-practice
cd packer-practice&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 작성한 Packer 템플릿은 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;source_ami는 AMI 카탈로그에서 참조하거나 private으로 사용하는 ami가 있다면 해당 ami를 사용해도 된다. 최신버전의 ami를 사용하고자 하는 경우 filter를 통해 조회 후 적용이 가능하다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1613&quot; data-origin-height=&quot;713&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mmAoD/btslb7lvcCO/L7nlGuxePJcp26L8dBwYDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mmAoD/btslb7lvcCO/L7nlGuxePJcp26L8dBwYDK/img.png&quot; data-alt=&quot;EC2 콘솔에서 제공하는 AMI 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mmAoD/btslb7lvcCO/L7nlGuxePJcp26L8dBwYDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmmAoD%2Fbtslb7lvcCO%2FL7nlGuxePJcp26L8dBwYDK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;320&quot; data-origin-width=&quot;1613&quot; data-origin-height=&quot;713&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;EC2 콘솔에서 제공하는 AMI 목록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# packer-aws-linux.pkr.hcl 

locals {
  timestamp = regex_replace(timestamp(), &quot;[- TZ:]&quot;, &quot;&quot;)
}

source &quot;amazon-ebs&quot; &quot;packer-ami&quot; {
  region          = &quot;ap-northeast-2&quot; # AMI를 생성할 리전 
  ami_name        = &quot;packer-aws-${local.timestamp}&quot;
  source_ami      = &quot;ami-0a0064415cdedc552&quot; # Amazon Linux 2 AMI (HVM)
  vpc_id          = &quot;vpc-id&quot; # AMI가 생성될 VPC
  subnet_id       = &quot;subnet-id&quot; # AMI가 생성될 Subnet
  instance_type   = &quot;t2.micro&quot;
  ssh_interface   = &quot;public_ip&quot;
  ssh_username    = &quot;ec2-user&quot; # Linux ssh user (ubuntu일 경우 admin)
  ami_description = &quot;Nginx with Amazon Linux2&quot;
  assume_role {
    role_arn = &quot;arn:aws:iam::account-id:role/admin&quot;
  }

  tags = { # https://developer.hashicorp.com/packer/plugins/builders/amazon/ebs#build-shared-information-variables
    Base_AMI_ID   = &quot;{{ .SourceAMI }}&quot;
    Base_AMI_Name = &quot;{{ .SourceAMIName }}&quot;
  }
}

build {
  sources = [
    &quot;source.amazon-ebs.packer-ami&quot;
  ]

  provisioner &quot;ansible&quot; {
    playbook_file = &quot;playbook/playbook.yml&quot;
    use_proxy     = &quot;false&quot;
    user          = &quot;ec2-user&quot;

  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;packer&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;packer 블록은 terraform 구성 파일에서 terraform 블록과 유사한 역할을 한다. 구성을 적용하는 데 필요한 최소 요구 사항 ( required_version, required_plugins)과 같은 패커 자체의 동작에 대해 정의한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;source&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Packer가 새 머신 이미지를 생성하기 위해 소스 이미지를 찾아야하는 위치를 정의한다. build 블록에서 해당 source 블록을 참조하여 builder를 시작할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;build&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;build를 어떻게 수행할지에 대해 정의하는 블록이다. 어떤 &lt;a href=&quot;https://developer.hashicorp.com/packer/docs/builders&quot;&gt;builder&lt;/a&gt;(e.g.VirtualBox, VMware, Amazon EC2)를 사용할지, 어떤 방법으로 프로비저닝 할지 등을 지정한다.&lt;/li&gt;
&lt;li&gt;provisioner 블록을 포함시켜 ansible 함께 구성한다거나 &lt;a href=&quot;https://developer.hashicorp.com/packer/docs/templates/hcl_templates/blocks/build/post-processor&quot;&gt;post-processor&lt;/a&gt;를 사용하여 build의 결과물(artifact)을 어떻게 처리할지 정의할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;variables, locals, data&lt;/b&gt; 블록은 terraform에서와 유사한 용법으로 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 구성을 Initialize 한다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;packer init .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;init을 실행하면 packer는 구성 파일을 분석해서 필요한 플러그인을 식별하고 설치되어 있지 않다면 필요한 플러그인을 설치한다. 이때 빌더나 프로비저너와 관련된 항목은 관여하지 않고 오로지 플러그인만 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. packer 파일의 syntax에 문제가 없는지 확인하고 유효성 검사를 실시한다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;packer fmt packer-aws-linux.pkr.hcl 
packer validate packer-aws-linux.pkr.hcl&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Packer 이미지 빌드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. pakcer build 명령을 통해 이미지를 빌드해보겠다. build를 실행하면 Packer는 머신 이미지를 생성하고 Provisioner를 실행시킨다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;packer build packer-aws-linux.pkr.hcl&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;763&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cotA0B/btsldOstRl9/4Ab39z9mj55mlPpbFOESS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cotA0B/btsldOstRl9/4Ab39z9mj55mlPpbFOESS1/img.png&quot; data-alt=&quot; build가 성공한 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cotA0B/btsldOstRl9/4Ab39z9mj55mlPpbFOESS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcotA0B%2FbtsldOstRl9%2F4Ab39z9mj55mlPpbFOESS1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;763&quot; height=&quot;225&quot; data-origin-width=&quot;763&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; build가 성공한 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 콘솔에서 결과를 확인해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;build 명령 후 출력된 ami-id와 동일한 id의 이미지가 생성된 것을 확인할 수 있다. 태그도 의도했던대로 추가되었다. packer 템플릿에서 packer-aws-${local.timestamp}와 같이 AMI 이름에 생성된 시간이 찍히게 설정해두는데 정상적으로 반영되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;57&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SVXsl/btslmUrQHvX/3Gu1P7ym8Bt4ChEBTpbbCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SVXsl/btslmUrQHvX/3Gu1P7ym8Bt4ChEBTpbbCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SVXsl/btslmUrQHvX/3Gu1P7ym8Bt4ChEBTpbbCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSVXsl%2FbtslmUrQHvX%2F3Gu1P7ym8Bt4ChEBTpbbCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;688&quot; height=&quot;40&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;57&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 13.png&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hyd2m/btslhbVfqVX/N34GiepwjSIf2owgMz3VTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hyd2m/btslhbVfqVX/N34GiepwjSIf2owgMz3VTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hyd2m/btslhbVfqVX/N34GiepwjSIf2owgMz3VTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHyd2m%2FbtslhbVfqVX%2FN34GiepwjSIf2owgMz3VTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;703&quot; height=&quot;183&quot; data-filename=&quot;img 13.png&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. AMI로 EC2 생성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성한 AMI로 EC2를 시작하여 ansible로 구성한 내역이 잘 들어갔는지 확인해봤다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dg1bHN/btsluf2QQ4s/eqgJXoKka1x8HrQQwxzvRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dg1bHN/btsluf2QQ4s/eqgJXoKka1x8HrQQwxzvRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dg1bHN/btsluf2QQ4s/eqgJXoKka1x8HrQQwxzvRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdg1bHN%2Fbtsluf2QQ4s%2FeqgJXoKka1x8HrQQwxzvRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;915&quot; height=&quot;298&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;298&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두 정상적으로 실행된 것을 확인할 수 있었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;packer는 처음 사용해보았는데, terraform을 사용하고 있어서 그런지 무리 없이 사용할 수 있었다. 여기서는 간단히 nginx를 설치하는 등의 작업만 진행했지만 실제로 애플리케이션을 미리 배포하고 구동하는 등의 작업을 playbook으로 실행하고 프로비저닝 해둔다면 auto scaling용 golden ami를 유지 관리하는데 큰 도움이 되겠다고 느꼈다. 꼭 프로덕션용으로 사용하지 않더라도 사내 표준 test base ami를 구성해두면 엔지니어나 개발자가 동일 환경에서 테스트 할 수 있다는 장점도 있을 것으로 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글에서는 github action을 사용해 packer나 ansible playbook에 변경사항이 있을 때 이를 감지하고 새롭게 이미지를 build하는 방법을 설명해보려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고자료&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.hashicorp.com/packer/tutorials/aws-get-started/aws-get-started-build-image?in=packer%2Faws-get-started&quot;&gt;https://developer.hashicorp.com/packer/tutorials/aws-get-started/aws-get-started-build-image?in=packer%2Faws-get-started&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.44bits.io/ko/post/building-docker-image-and-using-packer&quot;&gt;https://www.44bits.io/ko/post/building-docker-image-and-using-packer&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.hashicorp.com/packer/tutorials/aws-get-started/aws-get-started-build-image&quot;&gt;https://developer.hashicorp.com/packer/tutorials/aws-get-started/aws-get-started-build-image&lt;/a&gt;&lt;/p&gt;</description>
      <category>  CICD</category>
      <category>ansible</category>
      <category>cicd</category>
      <category>devops</category>
      <category>golden image</category>
      <category>immutable infrastructure</category>
      <category>Packer</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/20</guid>
      <comments>https://chnh.tistory.com/20#entry20comment</comments>
      <pubDate>Mon, 26 Jun 2023 14:07:00 +0900</pubDate>
    </item>
    <item>
      <title>GitHub Actions Workflow 문법 정리</title>
      <link>https://chnh.tistory.com/19</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;골든 이미지 파이프라인을 구성하면서 Github repo에 특정 이벤트가 발생했을 때 작업을 트리거하는 설정이 필요했다. 이 과정에서 Github Actions을 사용하게 되었고, 작업을 실행하는 workflow를 구성해야 했다. workflow는 리포지토리에 체크인된 YAML 파일에 의해 정의되기 때문에 파일 작성을 위한 syntax 공부가 필요했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에은 해당 workflow 구성 파일 작성을 위해 공식 문서를 보면서 정리한 내용이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Workflow syntax for GitHub Actions&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설명에 사용하는 전체 예제 코드는 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;# https://docs.github.com/en/actions/using-workflows/about-workflows

name: learn-github-actions
run-name: ${{ github.actor }} is learning GitHub Actions
on: [push]

jobs:
  check-bats-version:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '14'
      - run: npm install -g bats
      - run: bats -v&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 Github UI에서 다음과 같이 표현된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;641&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlrz0e/btskRbuIhOQ/k08ze0Vletrhin3PJyNIEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlrz0e/btskRbuIhOQ/k08ze0Vletrhin3PJyNIEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlrz0e/btskRbuIhOQ/k08ze0Vletrhin3PJyNIEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdlrz0e%2FbtskRbuIhOQ%2Fk08ze0Vletrhin3PJyNIEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;796&quot; height=&quot;399&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;641&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  name&lt;/b&gt; &lt;i&gt;- 선택사항&lt;/i&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;workflow의 이름. 리포지토리의 Actions 탭에 표시된다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;name: learn-github-actions&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  &lt;b&gt;run-name&lt;/b&gt; &lt;i&gt;- 선택사항&lt;/i&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;workflow에서 생성된 workflow 실행 이름&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리포지토리의 Actions 탭에 있는 workflow 실행 목록에 표시된다. 실행 이름이 작성되지 않은 경우 이벤트별 정보로 설정된다. 예를들어 &lt;code&gt;push&lt;/code&gt; 나 &lt;code&gt;pull_request&lt;/code&gt;에 의해 트리거된 workflow라면 커밋 메시지가 표시되는 식이다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;# 실행을 트리거한 github.actor의 이름을 표시
run-name: ${{ github.actor }} is learning GitHub Actions&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  on&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;workflow를 트리거하는 &lt;a href=&quot;https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows&quot;&gt;이벤트&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;on: [push, fork]&lt;/code&gt;와 같이 한 번에 여러 이벤트를 설정할 수도 있고, 시간을 지정하거나 특정 파일, 태그, 브랜치 변경이 발생한 경우에만 workflow가 실행되도록 제한할 수도 있다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;# branch에 상관없이 push가 발생할 때마다 workflow 실행
on: [push]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;on.&amp;lt;pull_request|pull_request_target&amp;gt;.&amp;lt;branches|branches-ignore&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pull_request 및 pull_request_target 이벤트를 사용할 때 특정 브랜치를 대상으로 하는 요청에 대해서만 워크플로우를 실행하도록 구성할 수 있다. 브랜치 이름은 *, **, +,?,! 같은 문자를 사용해서 패턴으로 정의하는 것도 가능하다. 특정 브랜치를 포함하는 것뿐만 아니라 &lt;a href=&quot;https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-excluding-branches&quot;&gt;특정 브랜치만 제외&lt;/a&gt;하는 것도 가능하다&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;# main 브랜치에 pull_request가 발생했을 때 workflow 실행 
on:
  pull_request:
    branches:    
      - main&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;on.push.&amp;lt;branches|tags|branches-ignore|tags-ignore&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;push 이벤트를 사용할 때 특정 브랜치 또는 태그에서 실행되도록 정의할 수도 있다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# 다음 대상에서 push 이벤트가 발생할 때 workflow 실행 
# - 브랜치 이름이 main, mona/octocat이거나 releases/로 시작하는 경우 
# - tag 이름이 v2이거나 v1.으로 시작하는 경우 
on:
  push:
    branches:    
      - main
      - 'mona/octocat'
      - 'releases/**'
    tags:        
      - v2
      - v1.*&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  jobs&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;workflow 실행은 하나 이상의 jobs로 구성된다. 이 job들은 &lt;b&gt;기본적으로 병렬로 실행&lt;/b&gt;되기 때문에 순차적인 작업 수행이 필요한 경우 jobs.&amp;lt;job_id&amp;gt;.needs 또는 steps 키워드를 사용해서 순차적으로 실행되도록 의존성을 추가해야한다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt; jobs:&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 job은 string 형식의 id를 가지며, run-on으로 지정된 러너 환경에서 실행된다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;# 최신버전의 ubuntu에서 실행되는 check-bats-version이라는 작업을 정의 
  check-bats-version:
    runs-on: ubuntu-latest&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;jobs.&amp;lt;job_id&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jobs 하위에 &lt;code&gt;job_id&lt;/code&gt;를 부여하여 각 작업을 구별할 수 있다. 다음 예시에서는 &lt;code&gt;job_id&lt;/code&gt;가 &lt;code&gt;my_first_job&lt;/code&gt;, &lt;code&gt;my_second_job&lt;/code&gt;인 두 개의 job이 생성되었다. &lt;code&gt;job_id&lt;/code&gt;의 하위 키는 해당 작업의 속성을 정의한다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;jobs:
  my_first_job:
    name: My first job
  my_second_job:
    name: My second job&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;jobs.&amp;lt;job_id&amp;gt;.name&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 정의한 name은 Github UI에 표시된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;jobs.&amp;lt;job_id&amp;gt;.needs&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 설명했듯 job은 기본적으로 병렬적으로 실행된다. needs 조건을 추가하면 종속성이 생성되어 특정 작업이 완료될때까지 다음 작업이 시작되지 않는다. 즉 종속성에 따라 암시적으로 순서가 정의되고, 하나라도 실패하면 해당 작업이 실행되지 않는다. 대신 종속성이 없는 작업의 경우 병렬적으로 실행된다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;# job2가 시작되기 전에 job1이 완료되어야 하고, job3을 실행하기 전에 job1,2가 성공해야한다. 
# job1, job2, job3이 순차적으로 실행되도록 하는 예시 
jobs:
  job1:
  job2:
    needs: job1
  job3:
    needs: [job1, job2]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;jobs.&amp;lt;job_id&amp;gt;. runs-on&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;job을 실행할 머신의 타입을 정의하는 부분이다. 머신의 유형에는 &lt;code&gt;Github-hosted runner&lt;/code&gt;와 &lt;code&gt;self-hosted runner&lt;/code&gt;가 있다.&lt;/p&gt;
&lt;pre class=&quot;apache&quot;&gt;&lt;code&gt;# linux, x64, and gpu 라벨을 가진 자체 호스팅 러너에서만 실행
runs-on: [self-hosted, linux, x64, gpu]&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;# GitHub-hosted runner로 최신 ubuntu 이미지 사용  
runs-on: ubuntu-latest&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 사용 가능한 GitHub-hosted runner 유형이다. &lt;i&gt;(2023.06.22 기준)&lt;/i&gt;&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;b&gt;Runner image&lt;/b&gt;&lt;/th&gt;
&lt;th&gt;&lt;b&gt;YAML workflow label&lt;/b&gt;&lt;/th&gt;
&lt;th&gt;&lt;b&gt;Notes&lt;/b&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Windows Server 2022&lt;/td&gt;
&lt;td&gt;windows-latest or windows-2022&lt;/td&gt;
&lt;td&gt;The windows-latest label currently uses the Windows Server 2022 runner image.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows Server 2019&lt;/td&gt;
&lt;td&gt;windows-2019&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ubuntu 22.04&lt;/td&gt;
&lt;td&gt;ubuntu-latest or ubuntu-22.04&lt;/td&gt;
&lt;td&gt;The ubuntu-latest label currently uses the Ubuntu 22.04 runner image.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ubuntu 20.04&lt;/td&gt;
&lt;td&gt;ubuntu-20.04&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS 13 Ventura [Beta]&lt;/td&gt;
&lt;td&gt;macos-13 or macos-13-xl&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS 12 Monterey&lt;/td&gt;
&lt;td&gt;macos-latest, macos-12, macos-latest-xl or macos-12-xl&lt;/td&gt;
&lt;td&gt;The macos-latest and macos-latest-xl workflow labels currently uses the macOS 12 runner image.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS 11 Big Sur&lt;/td&gt;
&lt;td&gt;macos-11&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;jobs.&amp;lt;job_id&amp;gt;.steps&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;steps&lt;/code&gt;를 사용하면 각 작업이 파일에 명시된 순서대로 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;jobs.&amp;lt;job_id&amp;gt;.steps[*].uses&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 단계의 일부로 실행할 작업을 선택하는 부분으로 &lt;code&gt;uses&lt;/code&gt; 값은 사용할 작업의 이름과 버전을 나타낸다. &lt;code&gt;{owner}/{repo}@{ref}&lt;/code&gt;와 같은 형식으로 표시된다. &lt;code&gt;actions/*&lt;/code&gt;는 Github에서 제공하는 공식 작업이다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;# actions 조직에서 만든 checkout 작업의 버전3을 사용
# checkout: https://github.com/actions/checkout
    steps:
      - uses: actions/checkout@v3

# Docker 컨테이너 이미지를 작업으로 사용
    steps:
      -  uses: docker://alpine:3.8&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;j&lt;/b&gt;&lt;b&gt;obs.&amp;lt;job_id&amp;gt;.steps[*].with&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;with&lt;/code&gt; 값은 특정 액션에 매개변수를 전달하는 데 사용된다. &lt;code&gt;with&lt;/code&gt; 키워드는 run 키워드가 사용되는 단계에서는 사용할 수 없다. &lt;code&gt;with&lt;/code&gt;에서 사용할 수 있는 매개변수는 각 액션의 문서에서 확인할 수 있다. &lt;i&gt;(checkout 액션에 대해 사용할 수 있는 with 값은 &lt;a href=&quot;https://github.com/actions/checkout#usage&quot;&gt;여기&lt;/a&gt;)&lt;/i&gt;&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;# node-version이 14라는 매개변수를 actions/setup-node@v3 액션에 전달
     steps:
      - uses: actions/setup-node@v3
        with:
          node-version: '14'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;j&lt;/b&gt;&lt;b&gt;obs.&amp;lt;job_id&amp;gt;.steps[*].run&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 단계별로 실행할 명령을 정의한다. 이 명령은 runner의 셸에서 실행된다.&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;# npm install -g bats 명령 실행 후 bats -v 명령 실행 
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '14'
      - run: npm install -g bats
      - run: bats -v&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;참고자료&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions&quot;&gt;https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>  CICD</category>
      <category>github-actions</category>
      <category>study-log</category>
      <category>syntax</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/19</guid>
      <comments>https://chnh.tistory.com/19#entry19comment</comments>
      <pubDate>Thu, 22 Jun 2023 17:36:50 +0900</pubDate>
    </item>
    <item>
      <title>키페어 없이 AWS CLI를 사용하여 EC2 인스턴스에 SSH로 연결하기</title>
      <link>https://chnh.tistory.com/18</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 ec2 인스턴스에 연결하려면 키페어가 필요했다. 아마 대부분 다음 명령어로 인스턴스에 접속했을 것이다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;ssh -i /path/key-pair-name.pem instance-user-name@instance-public-dns-name&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키페어를 관리하는 게 번거롭고 신경쓰이는 부분들이 많았다. &lt;i&gt;&lt;s&gt;만약 전임자가 퇴사하면서 키도 함께 삭제하거나 분실되면 ... &lt;/s&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크드인에서 팔로우하고있는 AWS 엔지니어의 &lt;a href=&quot;https://www.linkedin.com/posts/dennis-traub_aws-ec2-security-activity-7077179877187047425-zwvM?utm_source=share&amp;amp;utm_medium=member_desktop&quot;&gt;게시글&lt;/a&gt;을 통해 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이제&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;키페어 없이 instance id만 알고있다면 aws cli로 Linux 인스턴스에 연결할 수 있다는 소식을 알게됐다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스 연결 방법과 제한 사항에 대해 간단히 정리해보려한다. 아직 한국 공식 문서에는 올라오지 않았으나 영문 &lt;a href=&quot;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html#SSH-using-EC2-Instance-Connect&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문서&lt;/a&gt;에는 게시되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;EC2 Instance Connect란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2 Instance Connect는 일시적인 SSH 키를 사용해서 Linux 인스턴스에 접속하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 인스턴스 연결을 요청하면 Instance Connect API가 SSH 퍼블릭 키를 인스턴스 메타데이터에 푸시하고, SSH 데몬이 인스턴스 메타데이터에서 퍼블릭 키를 확인하여 사용자를 인스턴스에 연결해 준다. 이 때 사용자는 IAM 주체이고, 이 주체에게 키를 인스턴스에 푸시할 수 있는 권한이 있어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✔️ 2023.06.21 기준 &lt;code&gt;Amazon Linux 2&lt;/code&gt;와 &lt;code&gt;Ubuntu 16.04 이상&lt;/code&gt; 배포 버전에 대해서만 지원하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;AWS CLI로 Linux 인스턴스에 연결하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 &lt;u&gt;&lt;b&gt;퍼블릭&lt;/b&gt;&lt;/u&gt; 환경에 있는 인스턴스를 기준으로 설명한다. &lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/connect-using-eice.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;프라이빗 환경에 있는 인스턴스에는 엔드포인트를 통해 접근할 수 있다.&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. AWS CLI 업그레이드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 사용중이던 2.11.27 버전에서는 &lt;code&gt;ec2-instance-connect&lt;/code&gt; 커맨드를 인식하지 못했다. 2.12.1로 업그레이드 후 가능해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS CLI를 사용중이라면 업데이트를 하고, AWS CLI가 설치되어 있지 않다면 최신 버전으로 설치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;macOS를 사용중이라 다음 명령어로 업그레이드했다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;brew update
brew upgrade awscli&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 인스턴스 ID 조회&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이미 인스턴스 ID를 알고 있다면 생략 가능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔에서 직접 인스턴스 ID를 확인하거나, CLI에서 접속할 인스턴스 ID를 조회한다.&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;aws ec2 describe-instances&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 인스턴스 연결&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Public subnet에 위치한 인스턴스 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 명령어를 통해 인스턴스에 접속한다.&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;aws ec2-instance-connect ssh --instance-id [instance-id]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 3.png&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2PTqi/btskRaPWaLg/KGZBfH8FrVTgkcx0B1qfSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2PTqi/btskRaPWaLg/KGZBfH8FrVTgkcx0B1qfSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2PTqi/btskRaPWaLg/KGZBfH8FrVTgkcx0B1qfSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2PTqi%2FbtskRaPWaLg%2FKGZBfH8FrVTgkcx0B1qfSk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;783&quot; height=&quot;243&quot; data-filename=&quot;img 3.png&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성공 !&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Instance Connect는 콘솔에서도 사용할 수 있는 기능이었지만 CLI가 지원되면서 훨씬 간편하게 접속할 수 있게 되었다. 다만 전자금융감독규정상 Instance Connect를 사용하는 것 자체가 보안상 취약하다고 여겨지니, 상황에 따라 적절히 사용하시길 .. ! &lt;a href=&quot;https://rogue-gouda-f87.notion.site/AWS-de0b5749d03b464ea2e555cba3974d0b?p=3909989e0b224c75b5c81e6de351710d&amp;amp;pm=s&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;참고&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>☁️ AWS</category>
      <category>AWS</category>
      <category>AWSCLI</category>
      <category>devops</category>
      <category>Instance connect</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/18</guid>
      <comments>https://chnh.tistory.com/18#entry18comment</comments>
      <pubDate>Wed, 21 Jun 2023 22:30:22 +0900</pubDate>
    </item>
    <item>
      <title>System Manager로 특정 시간에 EC2 인스턴스 시작/중지 자동화하기</title>
      <link>https://chnh.tistory.com/17</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트용 EC2나 RDS는 퇴근 후에 사용하지 않는 경우가 대부분이다. 비용 절감을 위해 사용하지 않을 때 리소스를 정리해야하지만 퇴근 전에 인스턴스 중지하고 출근해서 다시 켜고하는 건 너무 귀찮고 비효율적이다. &lt;code&gt;Event Bridge&lt;/code&gt;와 &lt;code&gt;System Manager&lt;/code&gt;(이하 SSM)의 Automation Document을 사용하면 EC2 뿐만 아니라 RDS도 특정 시간에 시작하고 중지할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 요구사항이 있는 사람에게 이 글이 도움이 될 것이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;평일 오전9시에는 켜지고 오후9시가 되면 테스트 RDS가 중지되면 좋겠어요.&lt;/b&gt;&lt;br /&gt;&lt;b&gt;밤에만 사용하는 EC2가 있어서 매일 밤 10시에 켜지고 오전 6시에 꺼지게 해주세요.&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현 원리를 간단히 그림으로 표현해봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에서는 &lt;a href=&quot;https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-runbook-reference.html&quot;&gt;미리 정의된 Runbook&lt;/a&gt;을 제공하기 때문에 EC2 시작/중지 같이 사용 빈도가 높은 패턴들에 대해서는 사용자가 직접 스크립트를 구성하는 수고를 덜 수 있다. 특정 시간이 되면 이벤트가 발생하고, 이 이벤트가 SSM을 트리거하여 EC2를 시작/중지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;auto.drawio.png&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;281&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dreOFR/btsivPFX005/6EK0hyOcZJBPh4Velpqo0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dreOFR/btsivPFX005/6EK0hyOcZJBPh4Velpqo0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dreOFR/btsivPFX005/6EK0hyOcZJBPh4Velpqo0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdreOFR%2FbtsivPFX005%2F6EK0hyOcZJBPh4Velpqo0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;671&quot; height=&quot;281&quot; data-filename=&quot;auto.drawio.png&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;281&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. IAM 역할 생성하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2, RDS 인스턴스를 시작하거나 중지하기 위해 EventBridge와 SSM을 사용하려면 다음 두 IAM 역할이 필요하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EventBridge 실행 역할 (자동 생성)&lt;/li&gt;
&lt;li&gt;SSM Automation Document 실행 역할 (수동 생성)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1.1. 사용자 지정 정책 생성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EventBridge 실행 역할은 자동으로 생성되므로 여기서는 SSM Automation Document 실행 역할을 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. AWS Management Console에 로그인하고, IAM 콘솔로 이동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 왼쪽의 탐색 창에서 [정책]을 선택 &amp;gt; [정책 생성] 버튼을 클릭한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;JSON&lt;/b&gt; 탭을 선택하고 다음 정책들을 붙여넣는다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  SSM Automation Document 실행 역할에 필요한 IAM 정책&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
        {
            &quot;Sid&quot;: &quot;ssm&quot;,
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;ssm:StartAutomationExecution&quot;,
                &quot;ssm:DescribeAutomationExecutions&quot;,
                &quot;ssm:GetAutomationExecution&quot;
            ],
            &quot;Resource&quot;: &quot;*&quot;
        },
        {
            &quot;Sid&quot;: &quot;ec2&quot;,
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;ec2:StartInstances&quot;,
                &quot;ec2:StopInstances&quot;
            ],
            &quot;Resource&quot;: &quot;*&quot;
        },
        {
            &quot;Sid&quot;: &quot;rds&quot;,
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;rds:StartDBInstance&quot;,
                &quot;rds:StopDBInstance&quot;
            ],
            &quot;Resource&quot;: &quot;*&quot;
        }
    ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;ssm:StartAutomationExecution&lt;/code&gt;: 이 정책은 SSM이 자동화 문서를 시작할 수 있게 한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ssm:DescribeAutomationExecutions&lt;/code&gt;: 이 정책은 SSM이 자동화 실행의 상태를 설명하도록 한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ssm:GetAutomationExecution&lt;/code&gt;: 이 정책은 SSM이 특정 자동화 실행의 세부 정보를 가져올 수 있게 한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ec2:StartInstances&lt;/code&gt; and &lt;code&gt;ec2:StopInstances&lt;/code&gt;: 이들 정책은 SSM이 EC2 인스턴스를 시작하거나 중지할 수 있게 한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rds:StartDBInstance&lt;/code&gt; and &lt;code&gt;rds:StopDBInstance&lt;/code&gt;: 이들 정책은 SSM이 RDS 인스턴스를 시작하거나 중지할 수 있게 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 구분하기 쉬운 정책 이름을 입력하고 정책 생성을 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1.2. 역할 생성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. IAM 콘솔로 왼쪽의 탐색 창에서 [역할]을 선택 &amp;gt; &lt;b&gt;[역할 만들기]&lt;/b&gt; 버튼을 클릭한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 신뢰할 수 있는 엔터티 유형에서 AWS 서비스를 선택하고 System Manager를 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 권한 추가 단계에서 앞서 생성한 정책을 명을 검색한 다음 선택한다. 이때 정책 이름을 검색하고 확인이 안된다면 엔터를 눌러보시길 ..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 다음으로 넘어가 역할 생성 완료하면 끝 !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 지금 생성한 역할은 이후 규칙을 생성할 때 &lt;code&gt;AutomationAssumeRole&lt;/code&gt;에 입력해야 하므로 역할의 &lt;b&gt;ARN&lt;/b&gt; 주소를 &lt;b&gt;복사&lt;/b&gt;해 둔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 73.png&quot; data-origin-width=&quot;2294&quot; data-origin-height=&quot;586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btVVld/btsisph4QQ5/v91LpkcgDKQNZ7IKvvAmaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btVVld/btsisph4QQ5/v91LpkcgDKQNZ7IKvvAmaK/img.png&quot; data-alt=&quot;IAM 역할의 ARN, IAM 콘솔에서 확인할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btVVld/btsisph4QQ5/v91LpkcgDKQNZ7IKvvAmaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtVVld%2Fbtsisph4QQ5%2Fv91LpkcgDKQNZ7IKvvAmaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;731&quot; height=&quot;187&quot; data-filename=&quot;img 73.png&quot; data-origin-width=&quot;2294&quot; data-origin-height=&quot;586&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IAM 역할의 ARN, IAM 콘솔에서 확인할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. &lt;b&gt;Event Bridge 구성&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 평일 밤 9시마다 EC2가 종료되도록 구성해보겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. EventBridge 콘솔에서 규칙 생성을 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 원하는 규칙 이름(예: &lt;code&gt;stop-ec2-at-9pm&lt;/code&gt;)을 입력하고 규칙 유형을 &lt;code&gt;일정&lt;/code&gt;으로 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;a href=&quot;https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html#eb-cron-expressions&quot;&gt;cron식&lt;/a&gt;으로 실행 시간을 지정한다. 이 크론 식은 월-금 오후9시에 이벤트가 발생하게 한다.&amp;nbsp;&lt;code&gt;0 12 ? \* MON-FRI \*&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1564&quot; data-origin-height=&quot;1010&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkXKyD/btsisTchHAn/JfVHRCEKKAVhkKBZrKYcC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkXKyD/btsisTchHAn/JfVHRCEKKAVhkKBZrKYcC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkXKyD/btsisTchHAn/JfVHRCEKKAVhkKBZrKYcC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkXKyD%2FbtsisTchHAn%2FJfVHRCEKKAVhkKBZrKYcC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;633&quot; height=&quot;409&quot; data-origin-width=&quot;1564&quot; data-origin-height=&quot;1010&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 대상 유형을 다음과 같이 설정한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대상 유형: AWS 서비스&lt;/li&gt;
&lt;li&gt;대상 선택: &lt;code&gt;System Manager 자동화&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;문서: &lt;code&gt;AWS-StopEC2Instance&lt;/code&gt; (문서는 생성하려는 규칙에 따라 StartEC2Instance등으로 교체하면 된다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdBoxv/btsisv3PNK7/f88Pzh4FE22FXcmUGxcdlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdBoxv/btsisv3PNK7/f88Pzh4FE22FXcmUGxcdlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdBoxv/btsisv3PNK7/f88Pzh4FE22FXcmUGxcdlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdBoxv%2Fbtsisv3PNK7%2Ff88Pzh4FE22FXcmUGxcdlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;680&quot; height=&quot;253&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 규칙을 적용할 EC2 &lt;code&gt;인스턴스ID&lt;/code&gt;를 입력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 1.2단계에서 복사해둔 IAM 역할의 ARN을 &lt;code&gt;AutomationAssumeRole&lt;/code&gt;에 입력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 이 특정 리소스에 대해 새 역할 생성을 선택하고 규칙 생성을 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 자동화 실행 확인&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스 상태 변경 알람이나 직접 확인해보면 실행 여부를 확인할 수 있다. 실행 내역에 대해 자세히 확인하고 싶으면 SSM 콘솔에서 [변경관리] &amp;gt; [자동화] 메뉴에서 확인이 가능하다.&amp;nbsp;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다수의 인스턴스를 한번에 종료하려면 인스턴스 ID를 하나하나 넣어줘야하는 불편함이 있다. 인스턴수 수가 수십대가 되는 경우라면 EventBridge와 함께 Lambda를 사용하는 게 더 효율적일 것 같다. 편리할수록 종속성이 높고 자유도가 떨어진다는 것을 매번 깨닫게 된다. ㅠㅠ.  다음에는 태그값을 기반으로 인스턴스를 시작/중지할 수 있도록 구성해봐야겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>☁️ AWS</category>
      <category>SSM</category>
      <category>start-stop-ec2</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/17</guid>
      <comments>https://chnh.tistory.com/17#entry17comment</comments>
      <pubDate>Sat, 3 Jun 2023 00:53:57 +0900</pubDate>
    </item>
    <item>
      <title>EC2 상태 변경 알람 Slack으로 받아보기</title>
      <link>https://chnh.tistory.com/16</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 이전 포스팅에서 설명했던 EC2 상태 변경 알람을 Slack으로 받아보는 방법에 대해 다룬다. EC2 상태 변경 알람은 이벤트 패턴이 규정되어 있어서 따로 SNS 구독이나 CloudWatch 경보를 생성할 필요가 없다. 나는 개인용으로 사용할 거라 따로 Slack 앱을 생성하지 않고 Incoming Webhook을 사용할 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정을 수행하고 나면 EC2 상태가 변경됐을 때 다음과 같은 알람을 받게된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img 69.png&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wi0zY/btsigFp5w0G/7VFdKsWY2BSccN2fk83sv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wi0zY/btsigFp5w0G/7VFdKsWY2BSccN2fk83sv0/img.png&quot; data-alt=&quot;가트몬 이미지는 slack webhook icon을 변경했다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wi0zY/btsigFp5w0G/7VFdKsWY2BSccN2fk83sv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWi0zY%2FbtsigFp5w0G%2F7VFdKsWY2BSccN2fk83sv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;712&quot; height=&quot;140&quot; data-filename=&quot;img 69.png&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가트몬 이미지는 slack webhook icon을 변경했다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작동 방식을 간단히 그림으로 표현하면 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ec2.drawio.png&quot; data-origin-width=&quot;681&quot; data-origin-height=&quot;241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfSFJG/btsihcOVVbq/2knyY6D9s6iEnb8unKYuHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfSFJG/btsihcOVVbq/2knyY6D9s6iEnb8unKYuHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfSFJG/btsihcOVVbq/2knyY6D9s6iEnb8unKYuHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfSFJG%2FbtsihcOVVbq%2F2knyY6D9s6iEnb8unKYuHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;681&quot; height=&quot;241&quot; data-filename=&quot;ec2.drawio.png&quot; data-origin-width=&quot;681&quot; data-origin-height=&quot;241&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;구성 방법&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Slack Webhook 생성&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://saltwareteam.slack.com/apps%20&quot;&gt;Slack App directory&lt;/a&gt;에서 Incoming Webhook을 검색한다. Add to channel을 선택하고 알람을 수신받을 채널을 선택한다. 나는 개인적으로 받아볼거라 내 채널을 선택했다. &lt;img src=&quot;https://blog.kakaocdn.net/dn/uYXa1/btsic62NAUv/bxzhXWrco1QiFCb9gUsJQK/img.png&quot; alt=&quot;&quot; width=&quot;651&quot; height=&quot;176&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;채널 선택 후 Add incoming WebHooks integration 버튼을 클릭하면 다음과 같은 화면이 표시된다. 스크롤을 다운하면 Webhook URL을 복사할 수 있다. &lt;b&gt;Webhook URL&lt;/b&gt;을 다음 단계에서 &lt;b&gt;Lambda의 환경변수&lt;/b&gt;로 설정해준다.&lt;br /&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2EFgz/btsicOH21jN/qrfQw9df8rGwE6jrEcGC11/img.png&quot; alt=&quot;&quot; width=&quot;652&quot; height=&quot;100&quot; /&gt;&lt;/li&gt;
&lt;li&gt;여기서 이름과 아이콘도 설정이 가능하다. 여기서 설정한 아이콘은 나중에 Slack 알람의 프로필 사진이 된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2&lt;/b&gt;. &lt;b&gt;Lambda 함수 Deploy&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://ap-northeast-2.console.aws.amazon.com/lambda&quot;&gt;Lambda 콘솔&lt;/a&gt;에서 함수 생성을 선택한다.&lt;img src=&quot;https://blog.kakaocdn.net/dn/WFCV0/btsiacXQtLv/JFBlD81kehnsDTLKzcwyK1/img.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;li&gt;코드 소스를 입력하는 부분에 다음 함수를 붙여넣고 &lt;b&gt;Deploy&lt;/b&gt;를 클릭한다. 이 함수는 &lt;a href=&quot;https://github.com/jeongchanhui/lambda-sample-code/blob/main/cw-alarm-slack.py&quot;&gt;github&lt;/a&gt;에서 계속 업데이트 될 예정이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;# Slack Webhook으로 CloudWatch Event를 전송하는 함수 

from datetime import datetime, timedelta, timezone
import os
import urllib3
import json

# KST 시간대 정의 (UTC +9)
KST = timezone(timedelta(hours=9))

# Slack에 메시지를 전송하는 함수
def send_to_slack(webhook_url, msg):
    http = urllib3.PoolManager()
    encoded_msg = json.dumps(msg).encode('utf-8')
    resp = http.request('POST', webhook_url, body=encoded_msg)
    return resp

# Lambda 함수 핸들러
def lambda_handler(event, context):
    # 환경변수'SLACK_WEBHOOK_URL'에서 Slack Webhook URL 추출
    url = os.environ['SLACK_WEBHOOK_URL']     
    username = '[CloudWatch Alarm]' 
    pretext  = f'  [Event] {event[&quot;detail-type&quot;]}'
    account = event['account']

    # 이벤트 시간을 KST로 변환하고, 문자열로 변환
    time = datetime.fromisoformat(event['time'].replace('Z', '+00:00')).astimezone(KST)
    formatted_time = time.strftime('%Y-%m-%d %H:%M:%S KST')  # 'KST' added

    region = event['region']
    detail = event['detail']

    # 메시지 텍스트 작성
    senText  =  f'Account : {account}\nTime : {formatted_time}\nRegion : {region}\nDetail : {detail}'  # Changed {time} to {formatted_time}
    msg = {
        &quot;username&quot;: username,
        &quot;pretext&quot;: pretext,
        &quot;text&quot;: senText,
        &quot;icon_emoji&quot;: &quot;&quot;
    }

    # Slack에 메시지 전송    
    resp = send_to_slack(url, msg)

    # 응답 상태 및 본문 출력
    print({
        &quot;status_code&quot;: resp.status, 
        &quot;response&quot;: resp.data.decode('utf-8')
    })

    return {
        'statusCode': resp.status,
        'body': resp.data.decode('utf-8')
    }&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 환경 변수에 Webhook 입력&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드에 직접 Webhook을 입력하지 않도록하기 위해 환경변수를 사용하도록 구성했다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;구성 탭 &amp;gt; 환경 변수 &amp;gt; 환경 변수 편집을 선택한다.&lt;/li&gt;
&lt;li&gt;키를 &lt;b&gt;&lt;code&gt;SLACK_WEBHOOK_URL&lt;/code&gt;&lt;/b&gt; 로 입력한다.&lt;/li&gt;
&lt;li&gt;1단계에서 복사해둔 Webhook을 값으로 입력한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;203&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/twTtQ/btsicPmHObH/gIQn2gbB68cxzyJSHKo7E0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/twTtQ/btsicPmHObH/gIQn2gbB68cxzyJSHKo7E0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/twTtQ/btsicPmHObH/gIQn2gbB68cxzyJSHKo7E0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtwTtQ%2FbtsicPmHObH%2FgIQn2gbB68cxzyJSHKo7E0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;203&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;203&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Lambda 트리거 추가&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;함수 개요 부분에 있는 +트리거 추가 를 선택한다. &lt;img src=&quot;https://blog.kakaocdn.net/dn/dXru4N/btsh9F6LrVp/8f440wyuguxh99o8pLVrN1/img.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;li&gt;트리거 구성에서 &lt;b&gt;&lt;code&gt;EventBridge&lt;/code&gt;&lt;/b&gt;를 선택하고 다음과 같이 설정한다.&lt;br /&gt;규칙 유형: &lt;b&gt;&lt;code&gt;이벤트 패턴&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;EC2 / &lt;b&gt;&lt;code&gt;EC2 인스턴스 상태 변경 알림&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MeeoS/btsibfGaS1x/nakLT85khly1YlOxiExKO0/img.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;li&gt;저장하면 함수 개요 탭에서 트리거가 생성된 것을 확인할 수 있다.&lt;/li&gt;
&lt;li&gt;이후 EC2를 시작하거나 중지해보면 Slack 알람이 수신된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SNS 구독 설정 단계를 추가하면 State change 외에 다양한 CloudWatch 경보를 받아볼 수 있다. Lambda 함수를 변형해서 Slack으로 도착하는 메시지 내용과 형태를 변경할 수 있고, Slack에서 제공하는 API를 사용하여 대화형으로도 구성할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꼭 전파해야하는 이슈가 발생했을 때 공통 채널에 바로 게시할 수 있도록 설정해두면 의사소통 비용이 많이 줄어들 것으로 보인다. 다음에는 깃헙관련 내용으로 정리해봐야지.&amp;nbsp;&lt;/p&gt;</description>
      <category>☁️ AWS</category>
      <category>chatops</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/16</guid>
      <comments>https://chnh.tistory.com/16#entry16comment</comments>
      <pubDate>Thu, 1 Jun 2023 11:14:06 +0900</pubDate>
    </item>
    <item>
      <title>AWS User Notifications로 AWS EC2 상태 변경 알람 받기</title>
      <link>https://chnh.tistory.com/15</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; AWS 계정을 해킹당해서 다량의 gpu 인스턴스가 생성되어 채굴에 사용되는 경우가 있다. 애초에 해킹 당하지 않도록 보안에 주의해야겠지만, 만약 예상하지 않은 리소스 시작이 발생한다면 빠르게 알아차리고 대응할 수 있는 것도 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 조직 단위로 비용알람을 걸어놓은 경우에도 해커가 조직을 탈퇴시킨 뒤에 인스턴스를 띄워서 인지가 늦어지는 경우가 있었다. 따라서 EC2시작 중지가 발생할 경우 즉시 인지하고 대응할 수 있도록 대비해야한다. 이를 위해 EC2 상태가 변경되면 Slack으로 알람을 받도록 Event Brigde + Lambda를 사용해서 구성하여 사용하고있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;&amp;nbsp; 그런데 최근 &amp;nbsp;AWS User Notification이라는 기능이 새로 출시되어 간편하게 EC2 Status 변경 알람을 설정할 수 있게 됐다. EC2외에 다른 서비스에 대한 알람 서비스도 제공한다. EventBridge를 사용하지 않고 여러 알람을 중앙 집중화해서 관리할 수 있으니 개인 계정을 관리할 때 가볍게 사용하기 좋겠다는 생각이 든다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이 글에서는 콘솔을 사용해서 알람을 구성하고, 실제 Slack webhook을 사용해 구성한 알람과 어떤 차이가 있는지 살펴본다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;AWS User Notifications 구성 및 테스트&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;AWS User Notifications&lt;/b&gt; 서비스 콘솔로 들어간다.&lt;/li&gt;
&lt;li&gt;[알림 구성] &amp;gt; [알림 구성 생성]을 선택한다. AWS 서비스와 &lt;b&gt;특정한 이벤트 패턴&lt;/b&gt;을 선택할 수 있다. EC2외에도 여러 서비스들을 지원하고 있다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqDwdT/btshpYYmKZZ/J9skIXlevJibhPv6QbcW11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqDwdT/btshpYYmKZZ/J9skIXlevJibhPv6QbcW11/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1414&quot; data-origin-height=&quot;1650&quot; data-filename=&quot;img.png&quot; data-widthpercent=&quot;58.25&quot; style=&quot;width: 57.5489%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqDwdT/btshpYYmKZZ/J9skIXlevJibhPv6QbcW11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqDwdT%2FbtshpYYmKZZ%2FJ9skIXlevJibhPv6QbcW11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1414&quot; height=&quot;1650&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WKH4O/btshp2fmBgP/DP5z4rk7IHe29U91Maxdqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WKH4O/btshp2fmBgP/DP5z4rk7IHe29U91Maxdqk/img.png&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;1384&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;41.75&quot; style=&quot;width: 41.2434%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WKH4O/btshp2fmBgP/DP5z4rk7IHe29U91Maxdqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWKH4O%2Fbtshp2fmBgP%2FDP5z4rk7IHe29U91Maxdqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;850&quot; height=&quot;1384&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&amp;nbsp;고급 필터 기능을 통해 &lt;b&gt;특정 태그가 있는 인스턴스만&lt;/b&gt; 알람을 받도록 설정할 수 있다. &lt;img src=&quot;https://blog.kakaocdn.net/dn/dEVEna/btshkyTLSSJ/0Nsotrtv9F2ePEG6PrWRuk/img.png&quot; width=&quot;516&quot; height=&quot;218&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;484&quot; data-is-animation=&quot;false&quot; /&gt;&lt;/li&gt;
&lt;li&gt;집계 후 알람을 수신할 지 이벤트 발생 즉시 받을 지도 선택 가능하다.&amp;nbsp;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DTOXD/btshjdQkFy7/MWoASMOmnJNABQjYtS45v1/img.png&quot; width=&quot;702&quot; height=&quot;369&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;728&quot; data-is-animation=&quot;false&quot; /&gt;&lt;/li&gt;
&lt;li&gt;이후 알람을 받을 엔트포인트를 설정하고, 실제로 EC2를 시작시켜봤다. (테스트 전에 Email Verification 과정이 필요하다.) Slack은 버튼을 누르자마자 변경 알림이 오고, Email은 Slack알람 도착 후 바로 뒤에 도착했다. 실제 시간차이는 1초도 안날듯(?)
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;AWS User Notifications에서 발송된 Email&lt;br /&gt;&lt;img style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; src=&quot;https://blog.kakaocdn.net/dn/ebiQWP/btshp5K8BWi/oFu5dxVu6ekfQj5Uy7c1gK/img.png&quot; width=&quot;642&quot; height=&quot;501&quot; data-origin-width=&quot;2678&quot; data-origin-height=&quot;2090&quot; data-filename=&quot;blob&quot; data-is-animation=&quot;false&quot; /&gt;&lt;/li&gt;
&lt;li&gt;EventBridge에서 Slack으로 발송된 알람, 내용은 커스텀 가능하다. &lt;img style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; src=&quot;https://blog.kakaocdn.net/dn/dR57mh/btshmWVIYwu/KjfyXVxp2PAyr90yNNbIlk/img.png&quot; width=&quot;636&quot; height=&quot;129&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;236&quot; data-filename=&quot;blob&quot; data-is-animation=&quot;false&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에 사용자 편의를 고려한 서비스들이 점점 늘어나고 있는 것 같다. 기존에 여러 서비스를 결합해서 구성해야했던 것들을 하나의 서비스로 해결할 수 있게 하다니,, 어디까지 발전하려나 (?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS User Notification은 다음과 같은 사람들에게 추천하고 싶다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;알람을 받고싶긴 한데 어떻게 해야 하는지 잘 모르겠다.&lt;/li&gt;
&lt;li&gt;State change와 같은 특정 이벤트 패턴에 대해서만 알람이 필요하고, 발송되는 내용을 딱히 커스텀할 필요가 없다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;알람을 받는 채널이 Email, Chatbot, AWS App push로 충분하다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;메일로 수신할 때 텍스트만 있는게 아니라 포맷이 보기 좋게 되어있으면 한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;참고자료&lt;/b&gt;&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://aws.amazon.com/ko/blogs/korea/new-set-up-your-aws-notifications-in-one-place/&quot;&gt;https://aws.amazon.com/ko/blogs/korea/new-set-up-your-aws-notifications-in-one-place/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>☁️ AWS</category>
      <category>AWS</category>
      <category>cloudwatch</category>
      <category>user-notification</category>
      <author>chnh</author>
      <guid isPermaLink="true">https://chnh.tistory.com/15</guid>
      <comments>https://chnh.tistory.com/15#entry15comment</comments>
      <pubDate>Thu, 25 May 2023 19:24:59 +0900</pubDate>
    </item>
  </channel>
</rss>