컴공생의 발자취

AWS S3 보안 설정 및 정책 관리 (feat. IAM) 본문

🧡 AWS

AWS S3 보안 설정 및 정책 관리 (feat. IAM)

MNY 2024. 10. 14. 15:43
728x90
반응형
Keyword
  1. AWS IAM
  2. AWS S3
  3. AWS Bucket
  4. 정책 생성

 

Keyword
  1. IAM 설정 -> 이메일 보내기
  2. Bucket에 따른 보안 세팅
  3. 우리 DNS에서만 우리 Bucket 사용하도록 -> S3 config
  4. S3 Bucket마다 세팅 특정 IAM에서만 upload / read 가능

 

 권한 그룹 생성 

권한 그룹

* application.yml에 S3의 config가 들어가는데 이건 배포랑 개발할 때랑 다른 권한으로 사용하는 것을 권장

개발자 : ex) develper

배포 : ex) admin

 

그룹 권한(개발자 그룹)

* ✅ 표시는 실제 내가 포함한 그룹들

AmazonEC2FullAccess ✅

  • 설명: EC2 인스턴스 및 관련 리소스에 대한 전체 접근 권한을 부여합니다.
  • 사용 시점: 개발자가 EC2 인스턴스를 관리하고 사용할 필요가 있을 때 유용합니다.

AmazonS3FullAccess ✅

  • 설명: S3 버킷과 객체에 대한 전체 접근 권한을 부여합니다.
  • 사용 시점: 개발자가 S3 버킷을 생성, 삭제, 객체 업로드 및 다운로드 등의 작업을 수행해야 할 때 유용합니다.

AmazonDynamoDBFullAccess

  • 설명: DynamoDB 테이블과 데이터에 대한 전체 접근 권한을 부여합니다.
  • 사용 시점: 개발자가 DynamoDB를 사용하여 데이터베이스 작업을 수행해야 할 때 유용합니다.

AWSLambda_FullAccess ✅

  • 설명: Lambda 함수 및 관련 리소스에 대한 전체 접근 권한을 부여합니다.
  • 사용 시점: 개발자가 Lambda 함수를 생성, 관리, 배포할 때 유용합니다.

AmazonRDSFullAccess

  • 설명: RDS 인스턴스 및 관련 리소스에 대한 전체 접근 권한을 부여합니다.
  • 사용 시점: 개발자가 RDS 데이터베이스 인스턴스를 관리할 필요가 있을 때 유용합니다.

AWSCodeCommitFullAccess ✅

  • 설명: CodeCommit 리포지토리에 대한 전체 접근 권한을 부여합니다.
  • 사용 시점: 개발자가 소스 코드 버전 관리 및 리포지토리 관리를 해야 할 때 유용합니다.

AWSCodeBuildDeveloperAccess ✅

  • 설명: CodeBuild 프로젝트에 대한 접근 및 관리 권한을 부여합니다.
  • 사용 시점: 개발자가 CodeBuild를 사용하여 빌드 및 CI/CD 파이프라인을 관리할 때 유용합니다.

AWSCodeDeployFullAccess ✅

  • 설명: CodeDeploy 애플리케이션 및 배포 그룹에 대한 전체 접근 권한을 부여합니다.
  • 사용 시점: 개발자가 CodeDeploy를 사용하여 애플리케이션 배포를 관리할 때 유용합니다.

 

사용자 생성

사용자 생성:

  • 자동 생성 암호
  • 이메일로 해당 내용 보내주기

그룹 설정:

  • 앞서 만들었던 그룹으로 선택
  • 개발자 : developer

액세스키 발급받아서 전달:

  • 사용자 생성 후 액세스키 발급 후 엑셀로 파일을 받아서 전달해주기

 

 Bucket 정책 설정 

: S3 버킷에 대한 보안 설정은 주로 버킷 정책과 IAM 정책을 통해 관리합니다. 보안 설정을 통해 액세스를 제어하고, 데이터 보호를 강화할 수 있습니다. 다음은 S3 버킷에 대한 보안 설정 방법입니다.

 

Bucket 정책 설정

첫 번째 방법 - 특정 IP 주소에서만 접근 허용:

  1. S3 서비스에서 생성한 버킷을 클릭합니다.
  2. Permissions 탭으로 이동합니다.
  3. Bucket Policy를 클릭하여 버킷 정책을 설정합니다.
  4. 아래 JSON 정책을 입력하고 Save를 클릭합니다.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSpecificIP",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::my-developer-bucket",
        "arn:aws:s3:::my-developer-bucket/*"
      ],
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "203.0.113.0/24"
        }
      }
    }
  ]
}

 

 

두 번째 방법 - 특정 도메인에서만 접근 허용:

  1. Permissions 탭에서 Bucket Policy를 클릭합니다.
  2. 아래 JSON 정책을 입력하고 Save를 클릭합니다.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSpecificDomain",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::today-space/*",
      "Condition": {
        "StringLike": {
          "aws:Referer": [
            "http://today-space.com/*",
            "https://today-space.com/*",
            "http://localhost:8080"
          ]
        }
      }
    }
  ]
}

 

 

Bucket 정책 설정 예시:

  • 이 정책은 http://yourdomain.com 도메인에서만 버킷의 객체에 접근할 수 있도록 합니다. YOUR_BUCKET_NAMEyourdomain.com을 실제 값으로 대체해야 합니다.
  • S3 버킷마다 세팅 특정 IAM에서만 업로드 리드 가능
    • 특정 IAM 사용자나 그룹이 S3 버킷에 업로드 및 읽기 권한을 가지도록 설정하려면, IAM 정책을 생성하고 해당 사용자를 그 정책에 연결합니다.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSpecificDomain",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*",
      "Condition": {
        "StringLike": {
          "aws:Referer": "http://yourdomain.com/*"
        }
      }
    }
  ]
}

 

 IAM 정책 생성 

특정 IAM 사용자 또는 그룹에 대한 접근 권한 설정

  1. IAM 서비스로 이동합니다.
  2. Policies를 클릭하고 Create policy를 선택합니다.
  3. JSON 탭을 선택하고 다음 정책을 입력합니다.
json코드 복사
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject"
      ],
      "Resource": "arn:aws:s3:::my-developer-bucket/*"
    }
  ]
}

 

  1. Review policy를 클릭하고 정책에 이름을 지정합니다. (예: DeveloperBucketAccessPolicy)
  2. Create policy를 클릭하여 정책을 생성합니다.

 

정책을 사용자나 그룹에 연결

  1. IAM 서비스에서 Users 또는 Groups로 이동합니다.
  2. 해당 사용자나 그룹을 선택합니다.
  3. Permissions 탭에서 Add permissions를 클릭합니다.
  4. Attach policies를 선택하고 앞에서 생성한 정책을 선택합니다.
  5. Add permissions를 클릭하여 권한을 추가합니다.

 

 S3 버킷에 CORS 설정 추가 

  1. AWS Management Console에 로그인합니다.
  2. S3 서비스로 이동합니다.
  3. 설정할 버킷을 선택합니다.
  4. Permissions 탭으로 이동합니다.
  5. *Cross-origin resource sharing (CORS)**를 클릭합니다.
  6. 다음과 같은 JSON 형식의 CORS 규칙을 추가합니다.
[
  {
    "AllowedOrigins": [
      "http://yourdomain.com",
      "https://yourdomain.com"
    ],
    "AllowedMethods": [
      "GET",
      "PUT",
      "POST",
      "DELETE",
      "HEAD"
    ],
    "AllowedHeaders": [
      "*"
    ],
    "ExposeHeaders": [
      "x-amz-server-side-encryption",
      "x-amz-request-id",
      "x-amz-id-2"
    ],
    "MaxAgeSeconds": 3000
  }
]

 

위의 CORS 규칙 설명:

  • AllowedOrigins: 접근을 허용할 도메인을 지정합니다. httphttps를 모두 포함시켰습니다.
  • AllowedMethods: 허용할 HTTP 메서드를 지정합니다. (예: GET, PUT, POST, DELETE, HEAD)
  • AllowedHeaders: 허용할 HTTP 헤더를 지정합니다. ``로 모든 헤더를 허용할 수 있습니다.
  • ExposeHeaders: 클라이언트에 노출할 헤더를 지정합니다.
  • MaxAgeSeconds: CORS 응답을 캐시할 시간(초)입니다.

 

 Jenkins Script 환경변수 추가 

* 백엔드 pipeline script

pipeline {
    agent any

    environment {
        // Docker Hub credentials
        DOCKER_HUB_CREDENTIALS = 'docker-hub-credentials'
        DOCKER_HUB_REPO = 'ysy561356/today-space-back'
        DOCKER_CONTAINER = 'back-today-space-container'  // 여기에서 프로퍼티 정의
        
        // Github credentials
        GIT_CREDENTIALS_ID = 'github-token'
        GIT_BRANCH = 'release'
        GIT_URL = 'https://github.com/today-space/today-space-back.git'
        
        // EC2
        SSH_CREDENTIALS_ID = 'ec2-ssh-key'
        EC2_USER = 'ubuntu'
        EC2_DOMAIN = 'back.today-space.com'
        DOCKER_IMAGE_TAG = 'latest'
        
        // DB
        DB_URL = 'jdbc:postgresql://postgresql.today-space.com:5432/space'
        DB_USERNAME = 'youngju'
        DB_PASSWORD = '4564'
        
        // JWT
        JWT_SECRET_KEY = '7Iqk7YyM66W07YOA7L2U65Sp7YG065+9c3ByaW5n7Ius7ZmU7KO87LCo7JWE7JuD7IaM7Iux7ZSE66Gc7KCd7Yq47YyM7J2067iM66CI7KCE65Oc7YyAand0c2VjcmV0a2V5'
        JWT_ACCESS_TOKEN_EXPIRATION = 1800000
        JWT_REFRESH_TOKEN_EXPIRATION = 1209600000
        
        // S3
        BUCKET_NAME = 'today-space'
        ACCESS_KEY_ID = 'AKIATCKAMVLZ5NQSKIEX'
        SECRET_ACCESS_KEY = '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'
        
        // Social Login
        KAKAO_REST_API_KEY = '6cd61cbdb917a1046bf437980b1e2ac9'
        NAVER_REST_API_KEY = 'mgvICujU1zvQrtz_IQOA'
        NAVER_REST_API_SECRET_KEY = 'drUb2lRtGb'
        GOOGLE_REST_API_KEY = '878062679505-oh34mk7fm5mpipprk9o139i8if40b3qf.apps.googleusercontent.com'
        GOOGLE_REST_API_SECRET_KEY = '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'
    }

    stages {
        stage('Clone Git Repository') {
            steps {
                script {
                    // GitHub 저장소에서 코드 클론
                    git credentialsId: "${GIT_CREDENTIALS_ID}", branch: "${GIT_BRANCH}", url: "${GIT_URL}"
                    
                    // gradlew 파일에 실행 권한 부여
                    sh 'chmod +x gradlew'
                    
                    // Gradle 빌드
                    sh './gradlew build'
                    
                    // destination 디렉토리 생성
                    sh 'mkdir -p ../destination'
                    sh 'mkdir -p ../destination/build/libs'
                    
                    // JAR 파일과 Dockerfile을 특정 경로로 이동
                    sh 'cp build/libs/*.jar ../destination/build/libs'
                    sh 'cp Dockerfile ../destination/'
                }
            }
        }
        stage('Prepare .env') {
            steps {
                script {
                    sh '''
                    touch ../destination/back.env
                    echo DB_URL=$DB_URL > ../destination/back.env
                    echo DB_USERNAME=$DB_USERNAME >> ../destination/back.env
                    echo DB_PASSWORD=$DB_PASSWORD >> ../destination/back.env
                    echo JWT_SECRET_KEY=$JWT_SECRET_KEY >> ../destination/back.env
                    echo JWT_ACCESS_TOKEN_EXPIRATION=$JWT_ACCESS_TOKEN_EXPIRATION >> ../destination/back.env
                    echo JWT_REFRESH_TOKEN_EXPIRATION=$JWT_REFRESH_TOKEN_EXPIRATION >> ../destination/back.env
                    echo BUCKET_NAME=$BUCKET_NAME >> ../destination/back.env
                    echo ACCESS_KEY_ID=$ACCESS_KEY_ID >> ../destination/back.env
                    echo SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY >> ../destination/back.env
                    echo KAKAO_REST_API_KEY=$KAKAO_REST_API_KEY >> ../destination/back.env
                    echo NAVER_REST_API_KEY=$NAVER_REST_API_KEY >> ../destination/back.env
                    echo NAVER_REST_API_SECRET_KEY=$NAVER_REST_API_SECRET_KEY >> ../destination/back.env
                    echo GOOGLE_REST_API_KEY=$GOOGLE_REST_API_KEY >> ../destination/back.env
                    echo GOOGLE_REST_API_SECRET_KEY=$GOOGLE_REST_API_SECRET_KEY >> ../destination/back.env
                    '''
                }
            }
        }
        stage('Build Docker Image') {
            steps {
                script {
                    // Git 태그를 이용해 버전 설정
                    env.DOCKER_IMAGE_TAG = sh(script: 'git describe --tags', returnStdout: true).trim()
        
                    def gitTag = sh(returnStdout: true, script: 'git describe --tags --always').trim()
                    def dockerImage = docker.build("${DOCKER_HUB_REPO}:${gitTag}", "./")
                    
                    // 특정 경로로 이동
                    dir('../destination') {
                        // Docker 이미지 빌드
                        sh "docker build -t ${DOCKER_HUB_REPO}:${env.DOCKER_IMAGE_TAG} ."
                        
                        // Host OS에서 Docker 이미지 확인
                        sh "docker images | grep ${DOCKER_HUB_REPO}"
                    }
                }
            }
        }
        stage('Push Docker Image to Docker Hub') {
            steps {
                script {
                    // Docker Hub에 로그인
                    withCredentials([usernamePassword(credentialsId: DOCKER_HUB_CREDENTIALS, usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) {
                        sh 'echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin'
                    }
                    
                    // Docker 이미지 push
                    sh "docker push ${DOCKER_HUB_REPO}:${env.DOCKER_IMAGE_TAG}"
                    
                    // docker image remove
                    sh "docker rmi ${DOCKER_HUB_REPO}:${env.DOCKER_IMAGE_TAG}"
                }
            }
        }
        stage('Restart Docker Compose on EC2') {
            steps {
                script {
                    withCredentials([sshUserPrivateKey(credentialsId: "${SSH_CREDENTIALS_ID}", keyFileVariable: 'SSH_KEY')]) {
                        def sshKey = env.SSH_KEY
                        
                        // 권한 변경
                        sh 'chmod 400 ' + sshKey
                        
                        // env 복사
                        sh 'scp -v -o StrictHostKeyChecking=no -i ' + sshKey + ' ../destination/back.env ${EC2_USER}@${EC2_DOMAIN}:/home/ubuntu/config/'
                        
                        // docker 이미지 stop
                        //sh 'ssh -v -o StrictHostKeyChecking=no -i ' + sshKey + ' ${EC2_USER}@${EC2_DOMAIN} "docker-compose down --rmi all"'
                        
                        // docker pull
                        sh 'ssh -v -o StrictHostKeyChecking=no -i ' + sshKey + ' ${EC2_USER}@${EC2_DOMAIN} "docker pull ${DOCKER_HUB_REPO}:${DOCKER_IMAGE_TAG}"'
                        
                        // docker 태그 변경
                        sh 'ssh -v -o StrictHostKeyChecking=no -i ' + sshKey + ' ${EC2_USER}@${EC2_DOMAIN} "docker tag ${DOCKER_HUB_REPO}:${DOCKER_IMAGE_TAG} ${DOCKER_HUB_REPO}:latest"'

                        // docker run
                        sh 'ssh -v -o StrictHostKeyChecking=no -i ' + sshKey + ' ${EC2_USER}@${EC2_DOMAIN} "docker-compose up -d"'
                    }
                }
            }
        }
    }
    post {
        always {
            cleanWs()
        }
        success {
            echo 'Deployment successful!'
        }
        failure {
            echo 'Deployment failed!'
        }
    }
}

 

 

 

728x90
반응형