# Serverless.com 보안 {{#include ../banners/hacktricks-training.md}} ## 기본 정보 ### 조직 **조직**은 Serverless Framework 생태계 내에서 가장 높은 수준의 엔티티입니다. 이는 여러 프로젝트, 팀 및 애플리케이션을 포함하는 **집단 그룹**을 나타냅니다. 예를 들어 회사, 부서 또는 기타 대규모 엔티티가 될 수 있습니다. ### 팀 **팀**은 조직 내에서 접근 권한이 있는 사용자들입니다. 팀은 역할에 따라 구성원을 조직하는 데 도움을 줍니다. **`협력자`**는 기존 앱을 보고 배포할 수 있으며, **`관리자`**는 새로운 앱을 생성하고 조직 설정을 관리할 수 있습니다. ### 애플리케이션 **앱**은 조직 내에서 관련 서비스의 논리적 그룹화입니다. 이는 여러 서버리스 서비스로 구성된 완전한 애플리케이션을 나타내며, 이 서비스들은 함께 작동하여 일관된 기능을 제공합니다. ### **서비스** **서비스**는 서버리스 애플리케이션의 핵심 구성 요소입니다. 이는 전체 서버리스 프로젝트를 나타내며, 필요한 모든 함수, 구성 및 리소스를 캡슐화합니다. 일반적으로 `serverless.yml` 파일에 정의되며, 서비스에는 서비스 이름, 제공자 구성, 함수, 이벤트, 리소스, 플러그인 및 사용자 정의 변수를 포함한 메타데이터가 포함됩니다. ```yaml service: my-service provider: name: aws runtime: nodejs14.x functions: hello: handler: handler.hello ```
Function A **Function**는 AWS Lambda 함수와 같은 단일 서버리스 함수를 나타냅니다. 이벤트에 응답하여 실행되는 코드를 포함합니다. `serverless.yml`의 `functions` 섹션 아래에 정의되며, 핸들러, 런타임, 이벤트, 환경 변수 및 기타 설정을 지정합니다. ```yaml functions: hello: handler: handler.hello events: - http: path: hello method: get ```
이벤트 **이벤트**는 서버리스 함수를 호출하는 트리거입니다. 이들은 함수가 어떻게 그리고 언제 실행되어야 하는지를 정의합니다. 일반적인 이벤트 유형에는 HTTP 요청, 예약된 이벤트(크론 작업), 데이터베이스 이벤트, 파일 업로드 등이 포함됩니다. ```yaml functions: hello: handler: handler.hello events: - http: path: hello method: get - schedule: rate: rate(10 minutes) ```
리소스 **리소스**는 데이터베이스, 스토리지 버킷 또는 IAM 역할과 같이 서비스가 의존하는 추가 클라우드 리소스를 정의할 수 있게 해줍니다. 이들은 `resources` 섹션 아래에 지정되며, 종종 AWS의 CloudFormation 구문을 사용합니다. ```yaml resources: Resources: MyDynamoDBTable: Type: AWS::DynamoDB::Table Properties: TableName: my-table AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 ```
Provider **Provider** 객체는 클라우드 서비스 제공업체(예: AWS, Azure, Google Cloud)를 지정하고 해당 제공업체와 관련된 구성 설정을 포함합니다. 런타임, 지역, 단계 및 자격 증명과 같은 세부정보를 포함합니다. ```yaml yamlCopy codeprovider: name: aws runtime: nodejs14.x region: us-east-1 stage: dev ```
단계 및 지역 단계는 서비스가 배포될 수 있는 다양한 환경(예: 개발, 스테이징, 프로덕션)을 나타냅니다. 이는 환경별 구성 및 배포를 허용합니다. ```yaml provider: stage: dev ``` 지역은 리소스가 배포될 지리적 지역을 지정합니다. 이는 지연 시간, 규정 준수 및 가용성 고려 사항에 중요합니다. ```yaml provider: region: us-west-2 ```
플러그인 **플러그인**은 새로운 기능을 추가하거나 다른 도구 및 서비스와 통합하여 Serverless Framework의 기능을 확장합니다. 이들은 `plugins` 섹션에 정의되며 npm을 통해 설치됩니다. ```yaml plugins: - serverless-offline - serverless-webpack ```
레이어 **레이어**는 공유 코드 또는 종속성을 함수와 별도로 패키징하고 관리할 수 있게 해줍니다. 이는 재사용성을 촉진하고 배포 패키지 크기를 줄입니다. 레이어는 `layers` 섹션 아래에 정의되며 함수에서 참조됩니다. ```yaml layers: commonLibs: path: layer-common functions: hello: handler: handler.hello layers: - { Ref: CommonLibsLambdaLayer } ```
변수 및 사용자 정의 변수 **변수**는 배포 시 해결되는 자리 표시자를 사용하여 동적 구성을 가능하게 합니다. - **구문:** `${variable}` 구문은 환경 변수, 파일 내용 또는 기타 구성 매개변수를 참조할 수 있습니다. ```yaml functions: hello: handler: handler.hello environment: TABLE_NAME: ${self:custom.tableName} ``` * **사용자 정의 변수:** `custom` 섹션은 `serverless.yml` 전반에 걸쳐 재사용할 수 있는 사용자 특정 변수 및 구성을 정의하는 데 사용됩니다. ```yaml custom: tableName: my-dynamodb-table stage: ${opt:stage, 'dev'} ```
출력 **출력**은 서비스가 배포된 후 반환되는 값들을 정의하며, 리소스 ARN, 엔드포인트 또는 기타 유용한 정보가 포함됩니다. 이들은 `outputs` 섹션 아래에 지정되며, 종종 다른 서비스에 정보를 노출하거나 배포 후 쉽게 접근할 수 있도록 사용됩니다. ```yaml ¡outputs: ApiEndpoint: Description: "API Gateway endpoint URL" Value: Fn::Join: - "" - - "https://" - Ref: ApiGatewayRestApi - ".execute-api." - Ref: AWS::Region - ".amazonaws.com/" - Ref: AWS::Stage ```
IAM 역할 및 권한 **IAM 역할 및 권한**은 함수 및 기타 리소스에 대한 보안 자격 증명과 접근 권한을 정의합니다. 이들은 필요한 권한을 지정하기 위해 `provider` 또는 개별 함수 설정에서 관리됩니다. ```yaml provider: [...] iam: role: statements: - Effect: 'Allow' Action: - 'dynamodb:PutItem' - 'dynamodb:Get*' - 'dynamodb:Scan*' - 'dynamodb:UpdateItem' - 'dynamodb:DeleteItem' Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/${self:service}-customerTable-${sls:stage} ```
환경 변수 **변수**는 하드코딩하지 않고도 구성 설정 및 비밀을 함수에 전달할 수 있게 해줍니다. 이들은 제공자 또는 개별 함수의 `environment` 섹션 아래에 정의됩니다. ```yaml provider: environment: STAGE: ${self:provider.stage} functions: hello: handler: handler.hello environment: TABLE_NAME: ${self:custom.tableName} ```
종속성 **종속성**은 함수에 필요한 외부 라이브러리와 모듈을 관리합니다. 일반적으로 npm 또는 pip와 같은 패키지 관리자를 통해 처리되며, `serverless-webpack`과 같은 도구나 플러그인을 사용하여 배포 패키지와 함께 번들됩니다. ```yaml plugins: - serverless-webpack ```
후크 **후크**는 배포 생애 주기의 특정 지점에서 사용자 정의 스크립트나 명령을 실행할 수 있게 해줍니다. 이들은 플러그인을 사용하거나 `serverless.yml` 내에서 정의되어 배포 전후에 작업을 수행합니다. ```yaml custom: hooks: before:deploy:deploy: echo "Starting deployment..." ```
### 튜토리얼 이것은 공식 튜토리얼의 요약입니다 [**문서에서**](https://www.serverless.com/framework/docs/tutorial): 1. AWS 계정 생성 (Serverless.com은 AWS 인프라에서 시작) 2. serverless.com에 계정 생성 3. 앱 생성: ```bash # Create temp folder for the tutorial mkdir /tmp/serverless-tutorial cd /tmp/serverless-tutorial # Install Serverless cli npm install -g serverless # Generate template serverless #Choose first one (AWS / Node.js / HTTP API) ## Indicate a name like "Tutorial" ## Login/Register ## Create A New App ## Indicate a name like "tutorialapp) ``` 이것은 **app**인 `tutorialapp`을 생성했어야 하며, [serverless.com](serverless.com-security.md)에서 확인할 수 있고, `helloworld` 코드가 포함된 JS 코드가 있는 **`handler.js`** 파일과 해당 함수를 선언하는 **`serverless.yml`** 파일이 있는 `Tutorial`이라는 폴더를 생성했어야 합니다: {{#tabs }} {{#tab name="handler.js" }} ```javascript exports.hello = async (event) => { return { statusCode: 200, body: JSON.stringify({ message: "Go Serverless v4! Your function executed successfully!", }), } } ``` {{#endtab }} {{#tab name="serverless.yml" }} ```yaml # "org" ensures this Service is used with the correct Serverless Framework Access Key. org: testing12342 # "app" enables Serverless Framework Dashboard features and sharing them with other Services. app: tutorialapp # "service" is the name of this project. This will also be added to your AWS resource names. service: Tutorial provider: name: aws runtime: nodejs20.x functions: hello: handler: handler.hello events: - httpApi: path: / method: get ``` {{#endtab }} {{#endtabs }} 4. **대시보드**에서 AWS 공급자를 생성합니다: `https://app.serverless.com//settings/providers?providerId=new&provider=aws`. 1. `serverless.com`에 AWS 접근 권한을 부여하기 위해, 이 구성 파일을 사용하여 클라우드포메이션 스택을 실행하라는 요청이 있습니다 (이 글을 작성할 당시): [https://serverless-framework-template.s3.amazonaws.com/roleTemplate.yml](https://serverless-framework-template.s3.amazonaws.com/roleTemplate.yml) 2. 이 템플릿은 **`SFRole-`**라는 역할을 생성하며, **`arn:aws:iam::aws:policy/AdministratorAccess`**를 통해 `Serverless.com` AWS 계정이 역할에 접근할 수 있도록 허용하는 신뢰 ID를 갖습니다.
Yaml roleTemplate ```yaml Description: This stack creates an IAM role that can be used by Serverless Framework for use in deployments. Resources: SFRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: AWS: arn:aws:iam::486128539022:root Action: - sts:AssumeRole Condition: StringEquals: sts:ExternalId: !Sub "ServerlessFramework-${OrgUid}" Path: / RoleName: !Ref RoleName ManagedPolicyArns: - arn:aws:iam::aws:policy/AdministratorAccess ReporterFunction: Type: Custom::ServerlessFrameworkReporter Properties: ServiceToken: "arn:aws:lambda:us-east-1:486128539022:function:sp-providers-stack-reporter-custom-resource-prod-tmen2ec" OrgUid: !Ref OrgUid RoleArn: !GetAtt SFRole.Arn Alias: !Ref Alias Outputs: SFRoleArn: Description: "ARN for the IAM Role used by Serverless Framework" Value: !GetAtt SFRole.Arn Parameters: OrgUid: Description: Serverless Framework Org Uid Type: String Alias: Description: Serverless Framework Provider Alias Type: String RoleName: Description: Serverless Framework Role Name Type: String ```
신뢰 관계 ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::486128539022:root" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "ServerlessFramework-7bf7ddef-e1bf-43eb-a111-4d43e0894ccb" } } } ] } ```
5. 튜토리얼에서는 `createCustomer.js` 파일을 생성하라고 요청하며, 이 파일은 기본적으로 새로운 API 엔드포인트를 생성하고, `serverless.yml` 파일을 수정하여 **새로운 DynamoDB 테이블**을 생성하고, **환경 변수**를 정의하며, 생성된 람다를 사용할 역할을 설정하라고 요청합니다. {{#tabs }} {{#tab name="createCustomer.js" }} ```javascript "use strict" const AWS = require("aws-sdk") module.exports.createCustomer = async (event) => { const body = JSON.parse(Buffer.from(event.body, "base64").toString()) const dynamoDb = new AWS.DynamoDB.DocumentClient() const putParams = { TableName: process.env.DYNAMODB_CUSTOMER_TABLE, Item: { primary_key: body.name, email: body.email, }, } await dynamoDb.put(putParams).promise() return { statusCode: 201, } } ``` {{#endtab }} {{#tab name="serverless.yml" }} ```yaml # "org" ensures this Service is used with the correct Serverless Framework Access Key. org: testing12342 # "app" enables Serverless Framework Dashboard features and sharing them with other Services. app: tutorialapp # "service" is the name of this project. This will also be added to your AWS resource names. service: Tutorial provider: name: aws runtime: nodejs20.x environment: DYNAMODB_CUSTOMER_TABLE: ${self:service}-customerTable-${sls:stage} iam: role: statements: - Effect: "Allow" Action: - "dynamodb:PutItem" - "dynamodb:Get*" - "dynamodb:Scan*" - "dynamodb:UpdateItem" - "dynamodb:DeleteItem" Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/${self:service}-customerTable-${sls:stage} functions: hello: handler: handler.hello events: - httpApi: path: / method: get createCustomer: handler: createCustomer.createCustomer events: - httpApi: path: / method: post resources: Resources: CustomerTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: primary_key AttributeType: S BillingMode: PAY_PER_REQUEST KeySchema: - AttributeName: primary_key KeyType: HASH TableName: ${self:service}-customerTable-${sls:stage} ``` {{#endtab }} {{#endtabs }} 6. **`serverless deploy`** 명령어로 배포합니다. 1. 배포는 CloudFormation Stack을 통해 수행됩니다. 2. **람다 함수는 직접 URL이 아닌 API 게이트웨이를 통해 노출됩니다.** 7. **테스트합니다.** 1. 이전 단계에서는 API 엔드포인트 람다 함수가 배포된 **URL**을 출력합니다. ## Serverless.com의 보안 검토 ### **잘못 구성된 IAM 역할 및 권한** 과도하게 허용된 IAM 역할은 클라우드 리소스에 대한 무단 액세스를 허용하여 데이터 유출 또는 리소스 조작으로 이어질 수 있습니다. 람다 함수에 대한 권한이 지정되지 않으면, 로그 생성 권한만 있는 역할이 생성됩니다. ```json { "Version": "2012-10-17", "Statement": [ { "Action": [ "logs:CreateLogStream", "logs:CreateLogGroup", "logs:TagResource" ], "Resource": [ "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/jito-cranker-scripts-dev*:*" ], "Effect": "Allow" }, { "Action": ["logs:PutLogEvents"], "Resource": [ "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/jito-cranker-scripts-dev*:*:*" ], "Effect": "Allow" } ] } ``` #### **완화 전략** - **최소 권한 원칙:** 각 함수에 필요한 권한만 할당합니다. ```yaml provider: [...] iam: role: statements: - Effect: 'Allow' Action: - 'dynamodb:PutItem' - 'dynamodb:Get*' - 'dynamodb:Scan*' - 'dynamodb:UpdateItem' - 'dynamodb:DeleteItem' Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/${self:service}-customerTable-${sls:stage} ``` - **별도의 역할 사용:** 함수 요구 사항에 따라 역할을 구분합니다. --- ### **안전하지 않은 비밀 및 구성 관리** 민감한 정보(예: API 키, 데이터베이스 자격 증명)를 **`serverless.yml`** 또는 코드에 직접 저장하면 리포지토리가 손상될 경우 노출될 수 있습니다. **추천되는** 방법은 serverless.com의 **`serverless.yml`** 파일에서 환경 변수를 저장하는 것으로, `ssm` 또는 `s3` 공급자를 사용하여 **배포 시 이러한 소스에서 환경 값을 가져오고** **lambdas** 환경 변수를 **값이 없는 텍스트로 구성**하는 것입니다! > [!CAUTION] > 따라서 AWS 내에서 lambdas 구성을 읽을 수 있는 권한이 있는 사람은 **모든 이러한 환경 변수를 평문으로 접근할 수 있습니다!** 예를 들어, 다음 예제는 SSM을 사용하여 환경 변수를 가져옵니다: ```yaml provider: environment: DB_PASSWORD: ${ssm:/aws/reference/secretsmanager/my-db-password~true} ``` 그리고 이것이 **`serverless.yml`** 파일에 환경 변수 값을 하드코딩하는 것을 방지하더라도, 값은 배포 시점에 얻어지며 **람다 환경 변수 안에 평문으로 추가됩니다**. > [!TIP] > serveless.com을 사용하여 환경 변수를 저장하는 권장 방법은 **AWS 비밀에 저장**하고 비밀 이름만 환경 변수에 저장하며 **람다 코드가 이를 수집해야 합니다**. #### **완화 전략** - **비밀 관리자 통합:** **AWS Secrets Manager**와 같은 서비스를 사용합니다. - **암호화된 변수:** 민감한 데이터에 대해 Serverless Framework의 암호화 기능을 활용합니다. - **접근 제어:** 역할에 따라 비밀에 대한 접근을 제한합니다. --- ### **취약한 코드 및 종속성** 구식 또는 안전하지 않은 종속성은 취약점을 도입할 수 있으며, 부적절한 입력 처리는 코드 주입 공격으로 이어질 수 있습니다. #### **완화 전략** - **종속성 관리:** 종속성을 정기적으로 업데이트하고 취약점을 스캔합니다. ```yaml plugins: - serverless-webpack - serverless-plugin-snyk ``` - **입력 검증:** 모든 입력에 대해 엄격한 검증 및 정화를 구현합니다. - **코드 리뷰:** 보안 결함을 식별하기 위해 철저한 리뷰를 수행합니다. - **정적 분석:** 코드베이스의 취약점을 감지하기 위해 도구를 사용합니다. --- ### **부적절한 로깅 및 모니터링** 적절한 로깅 및 모니터링이 없으면 악의적인 활동이 감지되지 않을 수 있으며, 사건 대응이 지연될 수 있습니다. #### **완화 전략** - **중앙 집중식 로깅:** **AWS CloudWatch** 또는 **Datadog**와 같은 서비스를 사용하여 로그를 집계합니다. ```yaml plugins: - serverless-plugin-datadog ``` - **상세 로깅 활성화:** 민감한 데이터를 노출하지 않으면서 필수 정보를 캡처합니다. - **알림 설정:** 의심스러운 활동이나 이상 징후에 대한 알림을 구성합니다. - **정기 모니터링:** 잠재적인 보안 사건에 대해 로그 및 메트릭을 지속적으로 모니터링합니다. --- ### **불안전한 API 게이트웨이 구성** 열려 있거나 부적절하게 보호된 API는 무단 접근, 서비스 거부(DoS) 공격 또는 교차 사이트 공격에 악용될 수 있습니다. #### **완화 전략** - **인증 및 권한 부여:** OAuth, API 키 또는 JWT와 같은 강력한 메커니즘을 구현합니다. ```yaml functions: hello: handler: handler.hello events: - http: path: hello method: get authorizer: aws_iam ``` - **요청 속도 제한 및 조절:** 요청 속도를 제한하여 남용을 방지합니다. ```yaml provider: apiGateway: throttle: burstLimit: 200 rateLimit: 100 ``` - **안전한 CORS 구성:** 허용된 출처, 메서드 및 헤더를 제한합니다. ```yaml functions: hello: handler: handler.hello events: - http: path: hello method: get cors: origin: https://yourdomain.com headers: - Content-Type ``` - **웹 애플리케이션 방화벽(WAF) 사용:** 악의적인 패턴에 대해 HTTP 요청을 필터링하고 모니터링합니다. --- ### **불충분한 함수 격리** 공유 리소스와 불충분한 격리는 권한 상승 또는 함수 간의 의도하지 않은 상호작용을 초래할 수 있습니다. #### **완화 전략** - **함수 격리:** 독립적인 작동을 보장하기 위해 고유한 리소스 및 IAM 역할을 할당합니다. - **리소스 분할:** 서로 다른 함수에 대해 별도의 데이터베이스 또는 저장소 버킷을 사용합니다. - **VPC 사용:** 향상된 네트워크 격리를 위해 가상 사설 클라우드 내에서 함수를 배포합니다. ```yaml provider: vpc: securityGroupIds: - sg-xxxxxxxx subnetIds: - subnet-xxxxxx ``` - **함수 권한 제한:** 함수가 명시적으로 요구되지 않는 한 서로의 리소스에 접근하거나 간섭할 수 없도록 합니다. --- ### **불충분한 데이터 보호** 정지 상태 또는 전송 중 암호화되지 않은 데이터는 노출될 수 있으며, 데이터 유출 또는 변조로 이어질 수 있습니다. #### **완화 전략** - **정지 상태 데이터 암호화:** 클라우드 서비스 암호화 기능을 활용합니다. ```yaml resources: Resources: MyDynamoDBTable: Type: AWS::DynamoDB::Table Properties: SSESpecification: SSEEnabled: true ``` - **전송 중 데이터 암호화:** 모든 데이터 전송에 대해 HTTPS/TLS를 사용합니다. - **API 통신 보안:** 암호화 프로토콜을 시행하고 인증서를 검증합니다. - **암호화 키를 안전하게 관리:** 관리형 키 서비스를 사용하고 키를 정기적으로 교체합니다. --- ### **적절한 오류 처리 부족** 상세한 오류 메시지는 인프라 또는 코드베이스에 대한 민감한 정보를 유출할 수 있으며, 처리되지 않은 예외는 애플리케이션 충돌로 이어질 수 있습니다. #### **완화 전략** - **일반 오류 메시지:** 오류 응답에서 내부 세부 정보를 노출하지 않도록 합니다. ```javascript javascriptCopy code// Node.js의 예 exports.hello = async (event) => { try { // 함수 로직 } catch (error) { console.error(error); return { statusCode: 500, body: JSON.stringify({ message: 'Internal Server Error' }), }; } }; ``` - **중앙 집중식 오류 처리:** 모든 함수에서 오류를 일관되게 관리하고 정화합니다. - **오류 모니터링 및 로깅:** 세부 정보를 최종 사용자에게 노출하지 않고 내부적으로 오류를 추적하고 분석합니다. --- ### **불안전한 배포 관행** 노출된 배포 구성 또는 CI/CD 파이프라인에 대한 무단 접근은 악의적인 코드 배포 또는 잘못된 구성을 초래할 수 있습니다. #### **완화 전략** - **CI/CD 파이프라인 보안:** 엄격한 접근 제어, 다단계 인증(MFA) 및 정기 감사 구현합니다. - **구성을 안전하게 저장:** 배포 파일에서 하드코딩된 비밀 및 민감한 데이터를 제거합니다. - **코드로서의 인프라(IaC) 보안 도구 사용:** **Checkov** 또는 **Terraform Sentinel**과 같은 도구를 사용하여 보안 정책을 시행합니다. - **불변 배포:** 불변 인프라 관행을 채택하여 배포 후 무단 변경을 방지합니다. --- ### **플러그인 및 확장 프로그램의 취약점** 검증되지 않거나 악의적인 제3자 플러그인을 사용하면 서버리스 애플리케이션에 취약점을 도입할 수 있습니다. #### **완화 전략** - **플러그인 철저 검토:** 통합 전에 플러그인의 보안을 평가하고 평판이 좋은 출처의 플러그인을 선호합니다. - **플러그인 사용 제한:** 공격 표면을 최소화하기 위해 필요한 플러그인만 사용합니다. - **플러그인 업데이트 모니터링:** 보안 패치를 활용하기 위해 플러그인을 최신 상태로 유지합니다. - **플러그인 환경 격리:** 잠재적인 손상을 방지하기 위해 플러그인을 격리된 환경에서 실행합니다. --- ### **민감한 엔드포인트 노출** 공개적으로 접근 가능한 함수 또는 제한 없는 API는 무단 작업에 악용될 수 있습니다. #### **완화 전략** - **함수 접근 제한:** VPC, 보안 그룹 및 방화벽 규칙을 사용하여 신뢰할 수 있는 출처로의 접근을 제한합니다. - **강력한 인증 구현:** 모든 노출된 엔드포인트가 적절한 인증 및 권한 부여를 요구하도록 합니다. - **API 게이트웨이를 안전하게 사용:** API 게이트웨이를 구성하여 입력 검증 및 속도 제한을 포함한 보안 정책을 시행합니다. - **사용하지 않는 엔드포인트 비활성화:** 더 이상 사용하지 않는 엔드포인트를 정기적으로 검토하고 비활성화합니다. --- ### **팀원 및 외부 협력자에 대한 과도한 권한** 팀원 및 외부 협력자에게 과도한 권한을 부여하면 무단 접근, 데이터 유출 및 리소스 남용으로 이어질 수 있습니다. 이 위험은 여러 개인이 다양한 수준의 접근 권한을 가진 환경에서 더욱 커지며, 공격 표면과 내부 위협의 가능성을 증가시킵니다. #### **완화 전략** - **최소 권한 원칙:** 팀원 및 협력자가 작업을 수행하는 데 필요한 권한만 가지도록 합니다. --- ### **액세스 키 및 라이센스 키 보안** **액세스 키** 및 **라이센스 키**는 Serverless Framework CLI와의 상호작용을 인증하고 권한을 부여하는 데 사용되는 중요한 자격 증명입니다. - **라이센스 키:** CLI를 통해 로그인할 수 있도록 하는 Serverless Framework 버전 4에 대한 인증에 필요한 고유 식별자입니다. - **액세스 키:** Serverless Framework Dashboard와 인증하기 위해 Serverless Framework CLI가 사용하는 자격 증명입니다. `serverless` cli로 로그인할 때 액세스 키가 **생성되어 노트북에 저장됩니다**. 또한 `SERVERLESS_ACCESS_KEY`라는 환경 변수로 설정할 수 있습니다. #### **보안 위험** 1. **코드 리포지토리를 통한 노출:** - 액세스 키 및 라이센스 키를 하드코딩하거나 실수로 버전 관리 시스템에 커밋하면 무단 접근이 발생할 수 있습니다. 2. **안전하지 않은 저장:** - 적절한 암호화 없이 환경 변수나 구성 파일 내에 평문으로 키를 저장하면 유출 가능성이 높아집니다. 3. **부적절한 배포:** - 안전하지 않은 채널(예: 이메일, 채팅)을 통해 키를 공유하면 악의적인 행위자에게 가로채질 수 있습니다. 4. **회전 부족:** - 키를 정기적으로 회전하지 않으면 키가 손상된 경우 노출 기간이 연장됩니다. 5. **과도한 권한:** - 광범위한 권한을 가진 키는 여러 리소스에서 무단 작업을 수행하는 데 악용될 수 있습니다. {{#include ../banners/hacktricks-training.md}}