GitHub 연동을 위한 방화벽

  • Post author:
  • Post category:칼럼
  • Post comments:0 Comments
  • Post last modified:March 10, 2020
This entry is part 6 of 13 in the series Cloud Security

AWS 내의 서버가 GitHub의 OAuth 서비스를 이용하려면 필연적으로 방화벽을 열어야 한다. 다행히 GitHub의 서버 주소는 Meta API를 호출해 받아올 수 있다.

~ # curl https://api.github.com/meta
{
  "verifiable_password_authentication": true,
  "github_services_sha": "2f2313161ed4f940a57ae3f0936eb8e9695bb8a8",
  "hooks": [
    "192.30.252.0/22",
    "185.199.108.0/22",
    "140.82.112.0/20"
  ],
  "git": [
    "192.30.252.0/22",
    "185.199.108.0/22",
    "140.82.112.0/20",
    "13.229.188.59/32",
    "13.250.177.223/32",
    "18.194.104.89/32",
    "18.195.85.27/32",
    "35.159.8.160/32",
    "52.74.223.119/32"
  ],
  "pages": [
    "192.30.252.153/32",
    "192.30.252.154/32",
    "185.199.108.153/32",
    "185.199.109.153/32",
    "185.199.110.153/32",
    "185.199.111.153/32"
  ],
  "importer": [
    "54.87.5.173",
    "54.166.52.62",
    "23.20.92.3"
  ]
}

AWS SG를 읽고 수정하려면 아래와 같이 네 가지 권한만 있으면 된다. 물론 Security Group의 ARN을 정확히 알고 있다면 Resource 를 특정지어서 더 보안을 강화해도 될 것이다.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:CreateSecurityGroup",
"ec2:DescribeSecurityGroup*",
"ec2:RevokeSecurityGroup*",
"ec2:AuthorizeSecurityGroup*"
],
"Resource": "*"
}
]
}

이제 재료는 준비되었으니 요리를 하면 된다. awscli 를 이용해 간단한 Bash 스크립트를 작성한다. 이 스크립트는 GitHub의 서버 주소를 가져와서 SGNAME  환경변수에 명시한 SG 의 값을 수정한다. 만약 SGNAME에 해당하는 SG가 없으면 새로운 SG를 생성한다.

#!/bin/bash -x
INTERFACE=$(curl –silent http://169.254.169.254/latest/meta-data/network/interfaces/macs/ | tr -d '/')
VPC_ID=$(curl –silent http://169.254.169.254/latest/meta-data/network/interfaces/macs/${INTERFACE}/vpc-id)
AWS_DEFAULT_REGION=$(curl –silent http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region)
DESCRIPTION="$(date)"
GROUP_IDS="$(aws ec2 describe-security-groups | jq –arg SG_NAME "${SG_NAME}" '.SecurityGroups[] | select(.GroupName | contains($SG_NAME)) | .GroupId' | tr -d '"')"
if [[ "${GROUP_IDS}" == "" ]]; then
aws ec2 create-security-group –vpc-id="${VPC_ID}" –group-name "${SG_NAME}" –description "Open to GitHub only" | jq .GroupId
fi
aws ec2 describe-security-groups | jq –arg SG_NAME "${SG_NAME}" '.SecurityGroups[] | select(.GroupName | contains($SG_NAME)) | .GroupId' | tr -d '"' | while read -r GroupId; do
IP_PERMISSIONS=$(aws ec2 describe-security-groups –filters "Name=group-id,Values=${GroupId}" | jq ".SecurityGroups[] | .IpPermissions")
if [[ -n "${IP_PERMISSIONS}" && "${IP_PERMISSIONS}" != "[]" ]]; then
aws ec2 revoke-security-group-ingress –group-id "${GroupId}" –ip-permissions "${IP_PERMISSIONS}"
fi
# 똑같은 아이피가 여러 번 등장해서 `authorize-security-group-ingress`가 실패하는 경우가 있으므로 일단 오류를 보고 하지 않게 무조건 성공 처리한다
curl –silent https://api.github.com/meta | jq '.hooks[]' | tr -d '"' | while read -r CidrIp; do
aws ec2 authorize-security-group-ingress –group-id "${GroupId}" –ip-permissions "[{ \"IpProtocol\": \"-1\", \"IpRanges\": [{\"CidrIp\": \"${CidrIp}\", \"Description\": \"hooks – ${DESCRIPTION}\"}]}]" | /bin/true
done
curl –silent https://api.github.com/meta | jq '.git[]' | tr -d '"' | while read -r CidrIp; do
aws ec2 authorize-security-group-ingress –group-id "${GroupId}" –ip-permissions "[{ \"IpProtocol\": \"-1\", \"IpRanges\": [{\"CidrIp\": \"${CidrIp}\", \"Description\": \"git – ${DESCRIPTION}\"}]}]" | /bin/true
done
curl –silent https://api.github.com/meta | jq '.pages[]' | tr -d '"' | while read -r CidrIp; do
aws ec2 authorize-security-group-ingress –group-id "${GroupId}" –ip-permissions "[{ \"IpProtocol\": \"-1\", \"IpRanges\": [{\"CidrIp\": \"${CidrIp}\", \"Description\": \"pages – ${DESCRIPTION}\"}]}]" | /bin/true
done
curl –silent https://api.github.com/meta | jq '.importer[]' | tr -d '"' | while read -r IpAddress; do
aws ec2 authorize-security-group-ingress –group-id "${GroupId}" –ip-permissions "[{ \"IpProtocol\": \"-1\", \"IpRanges\": [{\"CidrIp\": \"${IpAddress}/32\", \"Description\": \"importer – ${DESCRIPTION}\"}]}]" | /bin/true
done
done

이 스크립트는 AWS VPC 내부에서 작동하며 스스로 자신이 속한 Region과 VPC 정보를 가져오게끔 설계되었다. 그러므로 나의 로컬 머신이 아닌 AWS 원격 서버에서 CronJob을 돌려야 한다. 여기서는 해당 VPC에 속한 Kubernetes 클러스터에서 CronJob으로 실행한다.

apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: github-sg
labels:
app: github-sg
spec:
schedule: "30 18 * * *"
jobTemplate:
spec:
template:
metadata:
annotations:
iam.amazonaws.com/role: arn:aws:iam::111122223333:role/GitHubSecurityGroup
labels:
app: github-sg
spec:
containers:
name: github-sg
image: my/raven-bash
args:
/bin/bash
-c
"/scripts/register.sh"
env:
name: AWS_DEFAULT_REGION
value: ap-northeast-2
name: SENTRY_DSN
value: YOUR_SENTRY_DSN
volumeMounts:
name: scripts-d
mountPath: /scripts
volumes:
name: scripts-d
projected:
defaultMode: 500
sources:
configMap:
name: github-sg-scripts
items:
key: register.sh
path: register.sh
restartPolicy: Never
successfulJobsHistoryLimit: 10
failedJobsHistoryLimit: 10
view raw k8s-cronjob.yaml hosted with ❤ by GitHub

이 CronJob은 kube2iam 을 통해 앞서 기술한 IAM 정책을 부여 받아서 Security Group을 조회하고 수정한다.

스크립트가 다소 장황하나 기본적으로 하는 일은 매우 간단하기 때문에 이해하기 어렵지 않으리라 믿는다. 마지막으로 이 CronJob을 돌리는데 필요한 jq, awscli 등이 설치된 Docker 이미지를 빌드할 때 필요한 Dockerfile은 다음과 같다.

FROM python:3.7

# Set the timezone to KST
RUN cat /usr/share/zoneinfo/Asia/Seoul > /etc/localtime

RUN set -ex \
    && apt-get clean && apt-get update \
    && apt-get install – no-install-recommends -y groff \
    && rm -rf /var/lib/apt/lists/*

ADD https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 /usr/local/bin/jq
RUN chmod +x /usr/local/bin/jq

WORKDIR /usr/src/app

COPY requirements.txt ./

RUN pip install – upgrade pip
RUN pip install – no-cache-dir -r requirements.txt

마지막 줄에 등장하는 requirements.txt 파일에서 Sentry.io CLI 도구인 raven-bashawscli를 설치한다.

raven-bash
awscli

끝!

Kubernetes, DevSecOps, AWS, 클라우드 보안, 클라우드 비용관리, SaaS 의 활용과 내재화 등 소프트웨어 개발 전반에 도움이 필요하다면 도움을 요청하세요. 지인이라면 가볍게 도와드리겠습니다. 전문적인 도움이 필요하다면 저의 현업에 방해가 되지 않는 선에서 협의가능합니다.
follow me
  • 싸이월드 법인가 뭔가 화제였는데 이런 게 훨씬 현실적인 접근이다 https://t.co/fSB9LiMYzO
    24 hours ago
  • 시장을 좋게 보는 사람을 좋게 볼 근거를 찾고 그렇지 않은 사람은 나쁘게 볼 근거만 열심히 찾네. 그 반대로 해야 얻는 게 있을텐데
    1 day ago
  • 일본이 liberal country 라는 말이 마음에 걸리네 https://t.co/aLteP9gEE8
    2 days ago
Buy me a coffeeBuy me a coffee
×
Kubernetes, DevSecOps, AWS, 클라우드 보안, 클라우드 비용관리, SaaS 의 활용과 내재화 등 소프트웨어 개발 전반에 도움이 필요하다면 도움을 요청하세요. 지인이라면 가볍게 도와드리겠습니다. 전문적인 도움이 필요하다면 저의 현업에 방해가 되지 않는 선에서 협의가능합니다.
Latest Posts