Передача учетных данных учетной записи службы Google в Docker

Мой вариант использования немного отличается от других с этой проблемой, поэтому небольшое предварительное описание:

Я работаю над Google Cloud, и у меня есть «докеризованное» приложение Django. Часть приложения зависит от использования gsutil для перемещения файлов в / из корзины Google Storage. По разным причинам мы не хотим использовать Google Container Engine для управления нашими контейнерами. Скорее, мы хотели бы масштабировать по горизонтали, запустив дополнительные виртуальные машины Google Compute, которые, в свою очередь, будут запускать этот контейнер Docker. Подобно https://cloud.google.com/python/tutorials/bookshelf-on-compute-engine, за исключением того, что мы будем использовать контейнер, а не извлекать репозиторий git.

Виртуальная машина будет создана из базового образа Debian, а запуск и установка зависимостей (например, самого Docker) будет организована с помощью сценария запуска (например, gcloud compute instances create some-instance --metadata-from-file startup-script=/path/to/startup.sh).

Если я вручную создаю виртуальную машину, повышаю ее с помощью sudo -s, запускаю gsutil config -f (который создает файл учетных данных в /root/.boto), а затем запускаю мой контейнер докеров (см. Dockerfile ниже) с помощью

docker run -v /root/.boto:/root/.boto username/gs gsutil ls gs://my-test-bucket

тогда это работает. Однако это требует моего взаимодействия для создания файла Boto.

У меня вопрос: как передать учетные данные службы по умолчанию в контейнер Docker, который будет запускаться на этой новой виртуальной машине?

gsutil работает "из коробки" даже на "свежей" виртуальной машине Debian, поскольку он использует учетные данные вычислительного ядра по умолчанию, с которыми загружены все виртуальные машины. Есть ли способ использовать эти учетные данные и передать их в контейнер докера? После первого вызова gsutil на новой виртуальной машине я заметил, что он создает папки ~ / .gsutil и ~ / .config. К сожалению, установка обоих из них в Docker с помощью

docker run -v ~/.config/:/root/.config -v ~/.gsutil:/root/.gsutil username/gs gsutil ls gs://my-test-bucket

не решает мою проблему. Он говорит мне:

ServiceException: 401 Anonymous users does not have storage.objects.list access to bucket my-test-bucket.

Минимальный файл Dockerfile gsutil (не мой):

FROM alpine
#install deps and install gsutil
RUN apk add --update \
    python \
    py-pip \
    py-cffi \
    py-cryptography \
  && pip install --upgrade pip \
  && apk add --virtual build-deps \
    gcc \
    libffi-dev \
    python-dev \
    linux-headers \
    musl-dev \
    openssl-dev \
  && pip install gsutil \
  && apk del build-deps \
  && rm -rf /var/cache/apk/*
CMD ["gsutil"]

Дополнение: обходной путь:

С тех пор я решил свою проблему, но это довольно окольный путь, поэтому меня все еще интересует более простой способ, если это возможно. Все подробности ниже:

Во-первых, описание: я сначала создал учетную запись службы в веб-консоли. Затем я сохраняю ключевой файл JSON (назовите его credentials.json) в ведре хранилища. В сценарии запуска виртуальной машины GCE я копирую этот ключевой файл в локальную файловую систему (gsutil cp gs://<bucket>/credentials.json /gs_credentials/). Затем я запускаю свой докер-контейнер, монтируя этот локальный каталог. Затем при запуске контейнера докеров он запускает скрипт, который аутентифицирует credentials.json (который создает файл .boto внутри докера), экспортирует BOTO_PATH = и, наконец, я могу выполнять операции gsutil в контейнере Docker.

Вот файлы для небольшого рабочего примера:

Dockerfile:

FROM alpine
#install deps and install gsutil
RUN apk add --update \
    python \
    py-pip \
    py-cffi \
    py-cryptography \
    bash \
    curl \
  && pip install --upgrade pip \
  && apk add --virtual build-deps \
    gcc \
    libffi-dev \
    python-dev \
    linux-headers \
    musl-dev \
    openssl-dev \
  && pip install gsutil \
  && apk del build-deps \
  && rm -rf /var/cache/apk/*

# install the gcloud SDK- 
# this allows us to use gcloud auth inside the container
RUN curl -sSL https://sdk.cloud.google.com > /tmp/gcl \
      && bash /tmp/gcl --install-dir=~/gcloud --disable-prompts

RUN mkdir /startup
ADD gsutil_docker_startup.sh /startup/gsutil_docker_startup.sh
ADD get_account_name.py /startup/get_account_name.py

ENTRYPOINT ["/startup/gsutil_docker_startup.sh"]

gsutil_docker_startup.sh: принимает единственный аргумент, который представляет собой путь к файлу учетных данных учетной записи службы в формате JSON. Файл существует, потому что каталог на главном компьютере был смонтирован в контейнере.

#!/bin/bash

CRED_FILE_PATH=$1

mkdir /results

# List the bucket, see that it gives a "ServiceException:401"
gsutil ls gs://<input bucket> > /results/before.txt

# authenticate the credentials- this creates a .boto file:
/root/gcloud/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=$CRED_FILE_PATH

# need to extract the service account which is like:
# <service acct ID>@<google project>.iam.gserviceaccount.com"
SERVICE_ACCOUNT=$(python /startup/get_account_name.py $CRED_FILE_PATH)

# with that service account, we can locate the .boto file:
export BOTO_PATH=/root/.config/gcloud/legacy_credentials/$SERVICE_ACCOUNT/.boto

# List the bucket and copy the file to an output bucket for good measure
gsutil ls gs://<input bucket> > /results/after.txt
gsutil cp /results/*.txt gs://<output bucket>/

get_account_name.py:

import json
import sys
j = json.load(open(sys.argv[1]))
sys.stdout.write(j['client_email'])

Затем сценарий запуска GCE (выполняется автоматически при запуске виртуальной машины):

#!/bin/bash

# <SNIP>
# Install docker, other dependencies
# </SNIP>

# pull docker image
docker pull userName/containerName

# get credential file:
mkdir /cloud_credentials
gsutil cp gs://<bucket>/credentials.json /cloud_credentials/creds.json

# run container
# mount the host machine directory where the credentials were saved.
# Note that the container expects a single arg, 
# which is the path to the credential file IN THE CONTAINER
docker run -v /cloud_credentials:/cloud_credentials \ 
    userName/containerName /cloud_credentials/creds.json



Ответы (1)


Вы можете назначить Определенную учетную запись службы для вашего экземпляра, а затем используйте учетные данные приложения по умолчанию в своем коде. Пожалуйста, проверьте эти моменты перед тестированием.

  • Установите для области доступа экземпляра значение: «Разрешить полный доступ ко всем облачным API», как они есть не совсем функция безопасности
  • Установите правильную роль для своей служебной учетной записи: «Средство просмотра объектов хранилища».

Аутентификация Токен являются загружаются автоматически с помощью Учетные данные приложения по умолчанию через доступный сервер метаданных Google из вашего экземпляра, а также из ваших контейнеров Docker. Нет необходимости управлять какими-либо учетными данными.

def implicit():
  from google.cloud import storage

  # If you don't specify credentials when constructing the client, the
  # client library will look for credentials in the environment.
  storage_client = storage.Client()

  # Make an authenticated API request
  buckets = list(storage_client.list_buckets())
  print(buckets)

Я также быстро протестировал с докером и отлично работал

yann@test:~$ gsutil cat gs://my-test-bucket/hw.txt
Hello World
yann@test:~$ docker run --rm google/cloud-sdk gsutil cat gs://my-test-bucket/hw.txt
Hello World
person Yann C.    schedule 24.03.2020