用Python向Harperdb容器注入AWS秘密
#aws #python #kubernetes #harperdb

在这篇文章中,我们将看到如何以几种方式将用户名和密码秘密作为环境变量作为环境变量。首先,我们将介绍一些AWS秘密经理和IAM程序。然后我们将继续前往Docker和Kubernetes。

创建秘密

作为具有足够权限创建秘密的用户,登录到AWS控制台。访问AWS Cloud Shell并将您的秘密以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中。我们可以将其用于制定策略。我们还可以在将政策附加到小组的同时检索政策。

$ 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团队创建的访问密钥与开发人员共享。开发人员可以通过重述系统的秘密价值来对其进行测试。请注意,Appuser没有控制台访问,因此它无法通过控制台访问Cloud Shell。它是要以编程方式使用的。尽管有可能在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设置配置和凭据。创建和新目录并向它添加一个.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 var。

$ 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目录中创建文件的aws configure

$ 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"
}

它正在工作....

Docker / AWS CLI

让我们尝试使用Docker的第一次测试。我们将使用AWS检索秘密,将其设置为本地系统上的Env Var,并将其作为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

Python

这次我们将尝试一些Python代码,应从AWS中使用样本。

让我们首先在本地运行Python代码,看看它是否有效。

$ 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

Python容器

现在,我们将使用一个容器测试以前的方案,我们需要首先将代码容器化。让我们写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

Kubernetes

由于我们已经用Docker容器测试了Envvars作为文件的创建,因此我们可以将其用作POD中的初始容器。它创建的Envvars文件可以由Harperdb容器通过共享卷使用。

首先,我要标记本地图像,然后将其推向Docker Hub。这样我就可以将其拉到Pod的容器中。我将在这里使用我的Docker ID,并且已经登录了。

$ 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 var附加。

这是我们的豆荚清单:

$ 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群集上,可以在其上应用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

POD正在运行。让我们检查一下变量的豆荚

$ kubectl exec -it -c harperdb harperdb -- printenv | grep HDB
HDB_ADMIN_USERNAME=HDB_ADMIN
HDB_ADMIN_PASSWORD=password

都很好。因此,我们已经到达了帖子的结尾,让我们用摘要结束。

概括

因此,我们已经看到了将Harperdb秘密存储在AWS中,分配必需的IAM,通过AWS CLI检索这些秘密的程序,然后在本地使用Python。然后,我们对Python代码进行了容器,并使用了Docker和Kubernetes尝试了驱动器。在这里,我们已经使用了Harperdb的内置Inv vars来设置凭据,如果您想将AWS Cognito与HarperdB集成以进行身份​​验证,则可以检查此link。谢谢您的阅读:)