تزریق اسرار AWS به کانتینر HarperDB با پایتون
در این پست خواهیم دید که چگونه می توانیم اسرار نام کاربری و رمز عبور ذخیره شده در AWS را به عنوان متغیرهای محیطی به کانتینر HarperDB به چند روش تزریق کنیم. ابتدا، برخی از رویههای مدیر AWS Secrets و IAM را پوشش میدهیم. و سپس به Docker و Kubernetes می رویم.
راز ایجاد کنید
به عنوان کاربری که دارای مجوزهای کافی برای ایجاد یک راز است، وارد کنسول AWS شوید. به پوسته ابری AWS دسترسی پیدا کنید و راز خود را با فرمت JSON در یک فایل موقت قرار دهید.
$ cat > /tmp/.hdb_creds.json <<EOF
{
"HDB_ADMIN_USERNAME": "admin",
"HDB_ADMIN_PASSWORD": "password"
}
EOF
این فقط یک راز است، اما دارای دو جفت کلید-مقدار است.
از این فایل JSON برای ایجاد یک راز با aws cli استفاده کنید.
$ aws secretsmanager create-secret \
--name HdbCreds \
--secret-string \
file:///tmp/.hdb_creds.json
توجه داشته باشید که راز در منطقه پیشفرض که پوسته ابری راهاندازی شده است ایجاد میشود، زیرا ما به صراحت به منطقه بالا اشاره نکردهایم، در مورد من این است ap-south-1
.
همانطور که راز ایجاد می شود، می توانیم با خیال راحت فایل مخفی را حذف کنیم.
$ rm /tmp/.hdb_creds.json
راه اندازی کاربر
اطمینان حاصل کنید که کاربر فعلی مجوز انجام عملیات IAM زیر را دارد.
کاربر ایجاد کنید.
$ aws iam create-user --user-name appuser
ایجاد گروه
$ aws iam create-group --group-name appgroup
کاربر را به گروه اضافه کنید
$ aws iam add-user-to-group --user-name appuser --group-name appgroup
خط مشی
ARN مخفی را دریافت کنید و آن را به عنوان متغیر محیط ذخیره کنید.
$ export SECRET_ARN=`aws secretsmanager describe-secret --secret-id HdbCreds --output text --query ARN`
خط مشی را در یک فایل json بنویسید، که اجازه می دهد مقدار مخفی را از ARN مخفی خاص ما دریافت کنید.
$ cat /tmp/policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"$SECRET_ARN"
]
}
]
}
ما از env var استفاده کرده ایم SECRET_ARN
در فایل بالا، می توانیم از envsusbst برای جایگزینی آن با مقدار واقعی استفاده کنیم. برای آن باید gettext را نصب کنیم.
$ sudo yum install gettext -y
$ envsubst < /tmp/policy.json > /tmp/.policy.json
بنابراین، سیاست واقعی با ARN مخفی در حال حاضر وارد است /tmp/.policy.json
. ما می توانیم از آن برای ایجاد خط مشی استفاده کنیم. ما همچنین می توانیم خط مشی ARN را همانطور که لازم است در حین پیوست کردن خط مشی به گروه بازیابی کنیم.
$ POLICY_ARN=`aws iam create-policy --policy-name apppolicy --policy-document file:///tmp/.policy.json --query Policy.Arn`
خط مشی اکنون ایجاد شده است، ما خوب هستیم که فایل مخفی را حذف کنیم.
$ rm /tmp/.policy.json
اکنون می توانیم خط مشی را به گروه پیوست کنیم.
$ aws iam attach-group-policy --group-name appgroup --policy-arn $POLICY_ARN
کلید دسترسی
تا اینجا ما یک کاربر در داخل یک گروه ایجاد کردیم و به آن گروه اجازه خواندن مقدار مخفی را دادیم. اکنون میتوانیم یک کلید دسترسی ایجاد کنیم و آن را با تیم توسعهدهنده که از آن در برنامه خود برای احراز هویت استفاده میکنند، به اشتراک بگذاریم.
$ aws iam create-access-key --user-name appuser > /tmp/.access_key.json
$ cat /tmp/.access_key.json
{
"AccessKey": {
"UserName": "appuser",
"AccessKeyId": "AKIA4IRCWQQATYRH4XV2",
"Status": "Active",
"SecretAccessKey": "<hidden>",
"CreateDate": "2023-05-25T11:41:20+00:00"
}
}
کاربر توسعه دهنده
فرض کنید کلید دسترسی ایجاد شده توسط تیم devops با توسعه دهنده به اشتراک گذاشته شده است. توسعه دهنده می تواند آن را با aws cli با بازیابی مقدار مخفی به شرح زیر از سیستم خود آزمایش کند. توجه داشته باشید که appuser به کنسول دسترسی ندارد، بنابراین نمی تواند از طریق کنسول به پوسته ابری دسترسی پیدا کند. قرار است از آن به صورت برنامه نویسی استفاده شود. اگرچه ممکن است از حساب های مختلف از یک دستگاه با پروفایل های موجود در aws cli استفاده کنید.
ما بقیه پست را از دستگاه محلی دنبال می کنیم، نه پوسته ابری.
aws cli در صورت عدم وجود قابل نصب است.
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
توسعه دهنده باید پیکربندی و اعتبارنامه را برای aws تنظیم کند. دایرکتوری جدید ایجاد کنید و a اضافه کنید .env
به آن فایل کنید.
$ mkdir secret-injection
$ cd secret-injection/
$ cat > .env << EOF
AWS_ACCESS_KEY_ID=AKIA4IRCWQQA25E4Q7OC
AWS_DEFAULT_OUTPUT=text
AWS_DEFAULT_REGION=ap-south-1
AWS_SECRET_ACCESS_KEY=<hidden>
AWS_SECRET_NAME=HdbCreds
EOF
اینها را به تنظیمات env vars در سیستم صادر کنید.
$ export `cat .env | xargs`
$ printenv | grep AWS
AWS_DEFAULT_REGION=ap-south-1
AWS_ACCESS_KEY_ID=AKIA4IRCWQQA25E4Q7OC
AWS_SECRET_ACCESS_KEY=<hidden>
AWS_SECRET_NAME=HdbCreds
AWS_DEFAULT_OUTPUT=text
تنظیم env vars یکی از راههای اضافه کردن پیکربندی و اعتبار برای aws است. به طور متناوب، شما همچنین می توانید استفاده کنید aws configure
که ترجیح می دهد فایل ها را در ~/.aws
فهرست راهنما.
$ aws configure
AWS Access Key ID [None]: AKIA4IRCWQQATYRH4XV2
AWS Secret Access Key [None]: <hidden>
Default region name [None]: ap-south-1
Default output format [None]: text
این به طور خودکار ایجاد می کند .aws
دایرکتوری و دو فایل داخل آن.
$ cat ~/.aws/config
[default]
region = ap-south-1
output = text
$ cat ~/.aws/credentials
[default]
aws_access_key_id = AKIA4IRCWQQATYRH4XV2
aws_secret_access_key = <hidden>
ما می توانیم با .env method
همانطور که به هر حال ما یک متغیر اضافی برای تنظیم نام مخفی داریم.
راز بازیابی
بیایید سعی کنیم راز را از دستگاه توسعه دهنده بازیابی کنیم.
$ aws secretsmanager get-secret-value --secret-id $AWS_SECRET_NAME --query SecretString
{
"HDB_ADMIN_USERNAME": "admin",
"HDB_ADMIN_PASSWORD": "password"
}
آن کار می کند….
داکر / AWS CLI
بیایید اولین آزمایش خود را با Docker امتحان کنیم. ما اسرار را با aws بازیابی میکنیم، آنها را بهعنوان env vars در سیستم محلی تنظیم میکنیم و آن را به عنوان env vars به کانتینر docker ارسال میکنیم.
$ HDB_ADMIN_USERNAME=`aws secretsmanager get-secret-value --secret-id $AWS_SECRET_NAME --query SecretString | jq -r '.HDB_ADMIN_USERNAME'`
$ HDB_ADMIN_PASSWORD=`aws secretsmanager get-secret-value --secret-id $AWS_SECRET_NAME --query SecretString | jq -r '.HDB_ADMIN_PASSWORD'`
$ docker run -d -e HDB_ADMIN_USERNAME=$HDB_ADMIN_USERNAME -e HDB_ADMIN_PASSWORD=$HDB_ADMIN_PASSWORD harperdb/harperdb
ظرف HarperDB باید در حال اجرا باشد و میتوانیم مقادیر env vars را بررسی کنیم.
$ HDB_CTR_ID=`docker run -d -e HDB_ADMIN_USERNAME=$HDB_ADMIN_USERNAME -e HDB_ADMIN_PASSWORD=$HDB_ADMIN_PASSWORD harperdb/harperdb`
$ docker exec $HDB_CTR_ID printenv | grep HDB
HDB_ADMIN_USERNAME=admin
HDB_ADMIN_PASSWORD=password
پایتون
این بار سعی می کنیم با مقداری کد پایتون، نمونه ها از AWS در دسترس باشند.
بیایید ابتدا کد پایتون را به صورت محلی اجرا کنیم و ببینیم که آیا کار می کند یا خیر.
$ cat retrieve_secret.py
'''
This example does some modification on the AWS sample code, visit the AWS docs for samples:
https://aws.amazon.com/developer/language/python/
'''
import json
import os
import boto3
from botocore.exceptions import ClientError
from dotenv import load_dotenv
load_dotenv()
def get_secret():
'''
function to retrieve secret from aws secrets manager
iterate over its keys and create files, one each for each key
the name of the file will be the key and it's value is the file content
pass the following env vars:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION
AWS_SECRET_NAME
'''
secret_name = os.environ['AWS_SECRET_NAME']
# Create a Secrets Manager client
session = boto3.session.Session()
client = session.client(
service_name="secretsmanager"
)
try:
get_secret_value_response = client.get_secret_value(
SecretId=secret_name
)
except ClientError as client_error:
# For a list of exceptions thrown, see
# https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
raise client_error
# Decrypts secret using the associated KMS key.
secret = get_secret_value_response['SecretString']
# Your code goes here.
secret_dict = json.loads(secret)
for key, value in secret_dict.items():
with open(f'envvars/{key}', 'w', encoding='utf-8') as open_file:
print(f'writing {key}')
open_file.write(value)
get_secret()
boto3 و python-dotenv را نصب کنید.
$ pip install boto3
$ pip install python-dotenv
یک دایرکتوری با نام envvars ایجاد کنید.
$ mkdir envvars
کد را اجرا کنید.
$ python3 retrieve_secret.py
writing HDB_ADMIN_USERNAME
writing HDB_ADMIN_PASSWORD
این باید دو فایل در دایرکتوری envvars ایجاد می کرد.
$ ls envvars/
HDB_ADMIN_PASSWORD HDB_ADMIN_USERNAME
$ cat envvars/HDB_ADMIN_USERNAME; echo
admin
$ cat envvars/HDB_ADMIN_PASSWORD; echo
password
ظرف پایتون
اکنون سناریوی قبلی را با یک کانتینر آزمایش می کنیم، که برای آن ابتدا باید کد خود را کانتینری کنیم. بیایید dockerfile را بنویسیم.
$ cat dockerfile
FROM python
RUN pip install boto3
RUN pip install python-dotenv
WORKDIR /app
COPY retrieve_secret.py ./
CMD [ "python", "retrieve_secret.py" ]
اکنون می توانیم تصویر را بسازیم.
$ docker build -t retrieve_secret .
محتویات داخل دایرکتوری envvars را حذف کنید.
$ rm envvars/*
ظرف را اجرا کنید و ببینید کار می کند یا خیر.
$ docker run --env-file .env -v $PWD/envvars:/app/envvars retrieve_secret
writing HDB_ADMIN_USERNAME
writing HDB_ADMIN_PASSWORD
باید دوباره فایل ها در دایرکتوری envvars وجود داشته باشد.
$ ls envvars/
HDB_ADMIN_PASSWORD HDB_ADMIN_USERNAME
کوبرنتیس
از آنجایی که ما ایجاد envvars را به عنوان فایل با یک کانتینر docker آزمایش کردهایم، میتوانیم از آن به عنوان یک ظرف اولیه در یک Pod استفاده کنیم. فایلهای envvars که ایجاد میکند میتوانند توسط کانتینر harperdb از طریق یک حجم مشترک استفاده شوند.
ابتدا تصویر محلی را تگ می کنم و آن را به داکر هاب می برم. تا بتوانم آن را در ظرف غلاف بکشم. من از شناسه docker خود در اینجا استفاده می کنم و قبلاً وارد شده ام.
$ docker tag retrieve_secret s1405/retrieve_secret
$ docker push s1405/retrieve_secret
بیایید یک شی مخفی با ما ایجاد کنیم .env
فایل.
$ kubectl create secret generic aws-vars --from-env-file=.env
secret/aws-vars created
$ kubectl get secret aws-vars -o jsonpath={.data} | jq
{
"AWS_ACCESS_KEY_ID": "QUtJQTRJUkNXUVFBMjVFNFE3T0M=",
"AWS_DEFAULT_OUTPUT": "dGV4dA==",
"AWS_DEFAULT_REGION": "YXAtc291dGgtMQ==",
"AWS_SECRET_ACCESS_KEY": <hidden>,
"AWS_SECRET_NAME": "SGRiQ3JlZHM="
}
میتوانیم اینها را بهعنوان env vars در ظرف init خود وصل کنیم.
در اینجا مانیفست غلاف ما است:
$ cat harperdb.yaml
apiVersion: v1
kind: Pod
metadata:
name: harperdb
spec:
initContainers:
- name: fetch-secrets
image: s1405/retrieve_secret
envFrom:
- secretRef:
name: aws-vars
volumeMounts:
- name: envvars
mountPath: /app/envvars
containers:
- name: harperdb
image: harperdb/harperdb
volumeMounts:
- name: envvars
mountPath: /app/envvars
volumes:
- name: envvars
emptyDir: {}
من در یک خوشه kubernetes مبتنی بر دسکتاپ docker هستم، مانیفست pod را می توان روی آن اعمال کرد.
$ kubectl config current-context
docker-desktop
$ kubectl apply -f harperdb-pod.yaml
$ kubectl get po -w
NAME READY STATUS RESTARTS AGE
harperdb 0/1 Init:0/1 0 5s
harperdb 0/1 PodInitializing 0 5s
harperdb 1/1 Running 0 8s
^C
غلاف در حال اجراست. بیایید غلاف را برای متغیرها بررسی کنیم
$ kubectl exec -it -c harperdb harperdb -- printenv | grep HDB
HDB_ADMIN_USERNAME=HDB_ADMIN
HDB_ADMIN_PASSWORD=password
همه خوبن بنابراین، به پایان پست رسیدیم، اجازه دهید آن را با یک خلاصه تمام کنیم.
خلاصه
بنابراین، رویه مربوط به ذخیره اسرار HarperDB در AWS، اختصاص IAM مورد نیاز، بازیابی آن رازها از طریق aws cli و سپس با پایتون به صورت محلی را دیدهایم. سپس کد پایتون خود را محفظهای کردیم، تمرینها را با docker و kubernetes امتحان کردیم. در اینجا، ما از env vars داخلی HarperDB برای تنظیم اعتبار استفاده کردهایم، اگر به دنبال ادغام AWS cognito با HarperDB برای احراز هویت هستید، میتوانید این پیوند را بررسی کنید. ممنون که خواندید 🙂