برنامه نویسی

تزریق اسرار 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 برای احراز هویت هستید، می‌توانید این پیوند را بررسی کنید. ممنون که خواندید 🙂

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

همچنین ببینید
بستن
دکمه بازگشت به بالا