2022년 3월 29일 화요일

[ Python ] AES 양방향 암호화

 

모듈 설치

$ pip install pycryptodome


파이썬 코드

import base64
from Crypto import Random
from Crypto.Cipher import AES

class AES256():

    def __init__(self, key):
        self.bs = 128
        self.key = key.encode('utf-8')
        self.key = AES256.str_to_bytes(key)

    @staticmethod
    def str_to_bytes(data):
        u_type = type(b''.decode('utf8'))
        if isinstance(data, u_type):
            return data.encode('utf8')
        return data

    def _pad(self, s):
        return s + (self.bs - len(s) % self.bs) * AES256.str_to_bytes(chr(self.bs - len(s)%self.bs))

    @staticmethod
    def _unpad(s):
        return s[:-ord(s[len(s)-1:])]

    def encrypt(self, raw):
        raw = self._pad(AES256.str_to_bytes(raw))
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return base64.b64encode(iv + cipher.encrypt(raw)).decode('utf-8')

    def decrypt(self, enc):
        enc = base64.b64decode(enc)
        iv = enc[:AES.block_size]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')


aes256 = AES256('mypassword')
e_aes256 = aes.encrypt('password_encrypt')
print(e_aes256)    # VvDWrD2aDyc+2rsdfDhDKosnc2odl2HD2
print(aes256.decrypt(e_aes256))    # password_encrypt



2022년 3월 16일 수요일

[ Python ] No module named 'numpy.core._multiarray_umath' Error


[ 에러 ] 

numpy패키지 설치시 발생 



[ 원인 ]

1. Numpy가 지원하는 최신 Python version은 3.8로 3.9버전 이상 사용시 에러

2. 윈도우(개발환경)에서 pip install numpy로 설치한 패키지는 리눅스에서 컴파일이 안되므로, 

powershell이나 hyper-v를 통해 numpy를 재설치



2022년 3월 14일 월요일

[ Lambda ] 다른 계정의 IAM권한 사용


다른 계정의 IAM을 사용하여 

Lambda함수에서 다른계정의 S3, Athena, Glue 등을 컨트롤 

예제 : AAAA 계정의 람다함수를 통해 BBBB계정의 S3와 athena, glue테이블에 접근



[ 1 ] AAAA 계정에서 람다를 실행하는 iam role(my-lambda-etl-role)에 

AccessCrossIAMBBBB라는 정책을 생성한 후, 아래 스크립트 추가

(기존 role에 추가시 policy로 생성 후 연동)

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::BBBB:role/bbbb-lambda-etl-role"
} }



[ 2 ] BBBB 계정에서 'bbbb-lambda-etl-role' im role에 

신뢰 관계 탭에서 아래 스크립트 추가

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::AAAA:role/service-role/aaaa-lambda-etl-role"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

권한 탭에서 AAAA계정이 접근할 서비스 추가 (S3, Athena, Glue)




[ 3 ] AAAA계정의 lambda에서 코드 작성

# 샘플코드

def lambda_handler(event, context):
    print('start function')

    sts_connection = boto3.client('sts')
    acct_b = sts_connection.assume_role(
        RoleArn="arn:aws:iam::BBBB:role/role-on-source-account",
        RoleSessionName="cross_acct_lambda"
    )

    ACCESS_KEY = acct_b['Credentials']['AccessKeyId']
    SECRET_KEY = acct_b['Credentials']['SecretAccessKey']
    SESSION_TOKEN = acct_b['Credentials']['SessionToken']


    # create service client using the assumed role credentials
    session = boto3.Session(
        aws_access_key_id=ACCESS_KEY,
        aws_secret_access_key=SECRET_KEY,
        aws_session_token=SESSION_TOKEN,
    )



[ 4 ] LakeFormation 사용시

각 계정에서 role에 대한 table/location 공유설정


[ 5 ] 참조하는 BBBB계정의 S3 권한 설정

버킷->권한->버킷정책

{ "Version": "2012-10-17", "Statement": [ { "Sid": "DelegateS3Access", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::AAAA:root" }, "Action": "s3:*", "Resource": [ "arn:aws:s3:::my-bucket-name/*", "arn:aws:s3:::my-bucket-name" ] } ] }




참조 : 
https://aws.amazon.com/ko/premiumsupport/knowledge-center/lambda-function-assume-iam-role/?nc1=h_ls

2022년 3월 6일 일요일

[ Docker ] 도커파일

[ 도커파일이란? ]

  • Docker상에서 실행시킬 컨테이너의 구성 정보(미들웨어, OS, 어플리케이션 등)을 기술하기 위한 파일
  • 확장자는 필요없음
  • Dockerfile이란 파일명 말고 다른 파일명으로 쓸 수 있지만 build시 명시해줘야 함



[ Docker File을 이용한 Sample ]

Dockerfile

# 베이스 이미지 설정

FROM ubuntu:latest

(or dighests로 지정: FROM ubuntu@sha256:se21f... )


# Nginx 설치

RUN apt-get update && apt-get install -y -q nginx


# 파일 복사

COPY index.html /usr/share/nginx/html


# Nginx 시작

CMD ["nginx", "-g", "daemon off;"]


도커 build

# 도커 파일 build

$ docker build -t webapp:1.0 /dockerfile_path


# 빌드된 이미지 실행

$ docker run -d --name "web_nginx" -p 80:80 webapp


[ 도커파일 작성 명령어 ]

RUN

# Shell 형식으로 bin/sh 를 거쳐서 실행

RUN apt-get install -y nginx

# Shell을 경유하지 않고 실행

RUN ["/bin/bash","-c","apt-get install -y nginx"]


CMD

이미지를 바탕으로 생성된 컨테이너 안에서 명령을 실행

하나만 지정 가능하며, 여러 개 지정 시 마지막 명령만 유효

# 베이스 이미지 설정

FROM ubuntu:16.04

# Nginx설치

RUN apt-get -y install nginx

# 포트 지정

EXPOSE 80

# 서버 실행

CMD nginx -g 'daemon off;'  [or]  CMD ["nginx", "-g", "daemon off;"]


ENTRYPOINT

docker container run 명령을 실행했을 때 실행

# Docker file

# 베이스 이미지 설정

FROM ubuntu:16.04


# top 실행

ENTRYPOINT ["top"]

CMD ["-d", "10"]

실행

# CMD 명령에서 지정한 10초 간격

$ docker run -it --name sample sample-app

# 인자를 다시 주어 2초 간격으로 갱신

$ docker run -it --name sample sample-app -d 2



ONBUILD

ONBUILD 구문을 포함한 Dockerfile이 다음 빌드에서 

베이스 이미지로 설정 하였을 때, ONBUILD로 지정한 명령어를 설정

1.베이스 이미지 작성(Dockerfile.base)

# 베이스 이미지 설정

FROM ubuntu:16.04

# Nginx 설치

RUN apt-get -y update && apt-get -y upgrade

RUN apt-get -y install nginx

# 포트 지정

EXPOSE 80

# 웹 콘텐츠 배치

ONBUILD ADD website.tar /var/www/html

# Nginx 실행

CMD nginx -g "daemon off;'

 2. 베이스 이미지 빌드

$ docker build -t web-base -f Dockerfile.base .

3. 본 이미지  작성

From web-base

4. 본 이미지 빌드

$ docker build -t web-app .

$ docker run -d -p 80:80 web-app

# 이후 website.tar로 구성된 html, css 화면이 나오는지 확인


STOPSIGNAL

컨테이너를 종료할 때 송신하는 시그널 설정

STOPSIGNAL [시그널]


HEALTHCHECK

컨테이너 안에 프로세스 정상 작동 확인

#5분마다 가용 중인 웹서버를 5초 안에 표시할 수 있는지 확인

HEALTHCHECK --interval=5m(체크간격) --timeout=5s (체크타임아웃) CMD curl -f http://localhost/ || exit1

# 헬스 체크 결과는 docker contain inspect로 확인


ENV

key value형태로 환경변수 설정

# Docker file

ENV myName = "42 fire user" \   

    myOrder = book\ desck\ chair \

지정한 환경변수 변경시

docker run --env를 통해


WORKDIR

작업용 디렉토리 지정, 없으면 새로 생성

# Docker file

ENV DIRPATH second

WORKDIR /first/$DIRPATH


USER

도커파일의 명령어를 실행 할 사용자 지정

# Docker file

RUN ["adduser", "42F"]

RUN ["whoami"]      # root

USER 42F

RUN ["whoami"]      #42F


EXPOSE

실행 중인 컨테이너의 공개 포트 지정

# Docker file

EXPOSE 8080     # docker run -p 로도 설정 가능


ARG

도커파일 안에서 사용할 변수를 정의

# Docker file

ARG MYNAME = "42F"

RUN echo $MYNAME

실행 시

$ docker build . --build-arg    # MYNAME = "42F"

$ docker build . -build-arg MYNAME=70F    # MYNAME이 정의 되었어도 "70F"로 변수 재정의 됨


ADD

빌드 시, 이미지에 파일이나 디렉토리를 추가

# Docker file

ADD host.txt /docker_dir/


# 파일명 패턴 사용

ADD ho* /docker_dir/

ADD hos?.txt /docker_dir       # ? : 임의의 한 문자


# WORKDIR 명령어와 같이 사용 (경로 : /docker_dir/web/ ) cd역할

WORKDIR /docker_dir

ADD host.html /web


# 원격 파일 추가

ADD http://www.site.com/index.php /docekr_dir/web/

# 퍼미션이 600인 파일이 추가, URL을 통해 다운로드시 인증이 필요한 경우면 wget, curl을 사용


VOLUME

이미지에 볼륨을 추가

# Docker file

VOLUME /Mount PATH




2022년 2월 25일 금요일

[ Docker ] 명령어 (네트워크)

도커 네트워크

# 네트워크 목록 확인 (기본적으로 bridge, host, none 세 개의 네트워크가 셋팅)

$ docker network ls


# 컨테이너 상세스펙 조회 (Networks 부분 살펴보기, default = bridge)

$ docker inspect webserver


# 네트워크 생성

$ docker network create -d=bridge my-network

네트워크 생성 확인

$ docker network ls -f driver=bridge 


# 네트워크 연결

docker network connect[disconnect] my-network webserver

# 컨테이너 시작 시 연결

$ docker run -itd --name=webserver --net=my-network nginx


# 네트워크 상세정보 확인 (해당 네트워크를 사용하고 있는 컨테이너도 확인 가능)

$ docker network inspect my-network


# 네트워크 삭제

$ docker network rm my-network


2022년 2월 24일 목요일

[ Docker ] 명령어 ( container 관련 )


도커 컨테이너 생성 및 시작

# 컨테이너 생성 (이미지에 포함되는 디렉토리와 파일들의 스냅샷을 생성, 시작하진 않음)

$ docker create -name webserver nginx


# 컨테이너 생성 및 시작

$ docker run [-d:백그라운드 실행, -i:표준입력 열기, -t:tty 디바이스사용] webserver


# 컨테이너 생성 및 시작 후, 컨테이너에서 bash사용 가능한 대화모드

$ docker run -it --name "web" nginx /bin/bash


# 컨테이너 백그라운드로 실행 후 인수(ping명령어) 실행

$ docker run -d nginx -u root /bin/ping localhost (실행 후 컨테이너 종료)

$ docker run -d --rm nginx /bin/ping localhost (실행 후 컨테이너 삭제)


# 컨테이너 백그라운드 실행 인수 로그 확인

$ docker logs {container_id}


# 컨테이너 시작 

$ docker start webserver


# 컨테이너 중지

$ docker stop webserver


# 컨테이너 삭제

$ docker rm [-f:실행 중 컨테이너 강제 삭제] webserver


도커 컨테이너 네트워크

# 컨테이너 포트 맵핑

$ docker run -d -p 8080:80 nginx


# 컨테이너 dns 서버 지정

$ docker run -d --dns 192.168.1.100 nginx


# 컨테이너 호스트명 지정

$ docker run -h test.server --add-host test.client:192.168.1.2 nginx (/etc/hosts 를 확인)


# host os와 docker의 네트워크 연결을 bridge, --net 옵션 사용하여 변경사능

# 브릿지연결 | 네트워크x | 다른 컨테이너 네트워크 | 호스트OS 네트워크 | 사용자정의 네트워크

$ --net=[bridge | none | containser:<name | id> | host | NETWORK ]


도커 컨테이너 실행환경

# 자원을 지정하여 컨테이너 실행

# 옵션:  -c[cpu비율] -m[메모리] -v[호스트와 디렉토리공유]

$ docker run -c=512[기본비율 1024] -m=2g -v /user/home/:/usr/share/nginx/html nginx


# 환경변수 설정

$ docker run -it -e=env_list nginx /bin/bash


# 작업디렉토리 설정

# docker run -it -w=/my_home nginx /bin/bash


도커 컨테이너 조작

# 컨테이너 조회

$ docker ls [-a: 정지 중 인 컨테이너도 표시] [-f name:test : 이름으로 컨테이너 필터링]


# 컨테이너 상태 확인

$ docker stats webserver


# 실행 중인 컨테이너에 echo 실행

$ docker exec -it webserver /bin/echo "hello world"


# 실행 중 프로세스 확인

$ docker top webserver


# 컨테이너에서 프로세스가 전송되고 있는 포트 확인

$ docker port webserver
80/tcp -> 0.0.0.0:80


# 컨테이너 이름 변경

$ docker rename old_name new_name


# 컨테이너 안의 파일 복사

$ docker cp ./test.txt webserver:/tmp/test.txt


# 이미지 생성부터 컨테이너가 달라진 점(차분) 확인 [A:추가 D:삭제 C:수정]

$ docker diff webserver

C /run
A /run/nginx.pid
C /etc
C /etc/nginx
C /etc/nginx/conf.d


도커 컨테이너 추출

# 컨테이너로부터 이미지 작성

$ docker commit -a(작성자) "42Fire" -m(메세지) "nginx server" webserver 42Fire/nginx_web:v1

# 이미지 생성 확인

$ docker image inspect 42Fire/nginx_web:v1


# 컨테이너를 tar파일로 출력

$ docker export webserver > werb.tar

# tar파일로부터 이미지 작성

$ cat web.tar | docker import - 42Fire/webserver:v1


# 불필요 이미지/컨테이너 일괄 삭제

$ docker system prune -a(사용하지 않는 리소스 모두)


도커 볼륨과 마운트

참조 : https://www.daleseo.com/docker-volumes-bind-mounts/


[ AWS ] Python에서 Lambda 함수 실행 (with boto3)


boto3를 이용한 Lambda함수 실행  

import json

import sys

import boto3


params = {"username": username"info_list": [{"phone": phone, "age": age}]}

client = boto3.client(service_name='lambda', region_name="ap-northeast-2")

client.invoke(FunctionName="my_func", InvocationType='Event', Payload=json.dumps(params))


invoke 옵션

response = client.invoke(

    FunctionName='string',

    InvocationType='Event'|'RequestResponse'|'DryRun',

    LogType='None'|'Tail',

    ClientContext='string',

    Payload=b'bytes'|file,

    Qualifier='string'

)

Description

FunctionName : 람다 함수 이름

InvocationType : 

- Event : 비동기식으로 호출

- RequestResponse : 동기식으로 호출

- DryRun : 매개변수 값을 확인, 사용자or역할에 함수를 호출할 수 있는 권한 확인

LogType : AWS CloudTrail에 실행로그를 남짐. 동기식 호출에만 적용

Payload : 람다 함수에 Json으로 input 제공

Qualifier : 호출 할 함수 버전 또는 별칭을 지정



https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda.html#Lambda.Client.invoke