GAE AttributeError: objeto 'credenciais' tem nenhum atributo 'with_subject'

votos
1

Eu tenho um aplicativo python Eu quero implantar no App Engine (2ª Geração Python 3.7) em que eu uso uma conta de serviço com em todo o Domínio delegação habilitado para acessar os dados do usuário.

Localmente eu faço:

import google.auth
from apiclient.discovery import build

creds, project = google.auth.default(
    scopes=['https://www.googleapis.com/auth/admin.directory.user', ],
)
creds = creds.with_subject(GSUITE_ADMIN_USER)

service = build('admin', 'directory_v1', credentials=creds)

Isso funciona bem e, tanto quanto eu sei que é a atual maneira de fazer isso ao usar credenciais padrão do aplicativo (localmente Tenho GOOGLE_APPLICATION_CREDENTIALS definido).

O problema é que no GAE, quando implantado, a chamada para with_subjectaumentos: AttributeError: 'Credentials' object has no attribute 'with_subject'

Tenho habilitado delegação de grande domínio na conta de serviço GAE já.

O que é diferente entre os GOOGLE_APPLICATION_CREDENTIALS eu uso localmente e os de GAE quando ambos são contas de serviço com a delegação de todo o domínio?

Onde está .with_subject()em GAE?

O credsobjecto recebido é do tipo compute_engine.credentials.Credentials.

traceback completo:

Traceback (most recent call last):
  File /env/lib/python3.7/site-packages/gunicorn/arbiter.py, line 583, in spawn_worker
    worker.init_process()
  File /env/lib/python3.7/site-packages/gunicorn/workers/gthread.py, line 104, in init_process
    super(ThreadWorker, self).init_process()
  File /env/lib/python3.7/site-packages/gunicorn/workers/base.py, line 129, in init_process
    self.load_wsgi()
  File /env/lib/python3.7/site-packages/gunicorn/workers/base.py, line 138, in load_wsgi
    self.wsgi = self.app.wsgi()
  File /env/lib/python3.7/site-packages/gunicorn/app/base.py, line 67, in wsgi
    self.callable = self.load()
  File /env/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py, line 52, in load
    return self.load_wsgiapp()
  File /env/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py, line 41, in load_wsgiapp
    return util.import_app(self.app_uri)
  File /env/lib/python3.7/site-packages/gunicorn/util.py, line 350, in import_app
    __import__(module)
  File /srv/main.py, line 1, in <module>
    from config.wsgi import application
  File /srv/config/wsgi.py, line 38, in <module>
    call_command('gsuite_sync_users')
  File /env/lib/python3.7/site-packages/django/core/management/__init__.py, line 148, in call_command
    return command.execute(*args, **defaults)
  File /env/lib/python3.7/site-packages/django/core/management/base.py, line 353, in execute
    output = self.handle(*args, **options)
  File /srv/metanube_i4/users/management/commands/gsuite_sync_users.py, line 14, in handle
    gsuite_sync_users()
  File /env/lib/python3.7/site-packages/celery/local.py, line 191, in __call__
    return self._get_current_object()(*a, **kw)
  File /env/lib/python3.7/site-packages/celery/app/task.py, line 375, in __call__
    return self.run(*args, **kwargs)
  File /srv/metanube_i4/users/tasks.py, line 22, in gsuite_sync_users
    creds = creds.with_subject(settings.GSUITE_ADMIN_USER)
AttributeError: 'Credentials' object has no attribute 'with_subject'  

Pacotes (lista parcial):

google-api-core==1.5.0
google-api-python-client==1.7.4
google-auth==1.5.1
google-auth-httplib2==0.0.3
google-cloud-bigquery==1.6.0
google-cloud-core==0.28.1
google-cloud-logging==1.8.0
google-cloud-storage==1.13.0
google-resumable-media==0.3.1
googleapis-common-protos==1.5.3
httplib2==0.11.3
oauthlib==2.1.0
Publicado 08/11/2018 em 06:55
fonte usuário
Em outras línguas...                            


2 respostas

votos
1

É verdade que você não pode usar o with_subjectmétodo com GAE ou credenciais GCE. No entanto, existe uma solução que eu era capaz de começar a trabalhar no meu servidor GCE e eu diria que isso funciona com contas de serviço padrão do GAE também. A solução é construir novas credenciais usando a identidade da conta de serviço com desejado subjecte scopes. Um guia detalhado pode ser encontrado aqui , mas eu também irá explicar o abaixo processo.

Em primeiro lugar, a conta de serviço tem permissões para criar fichas conta de serviço para si. Isso pode ser feito indo para o projetos IAM and admin > Service accountspágina (certifique-se o painel de informação é visível, pode ser alternada a partir do canto superior direito). Copie o endereço de e-mail da conta de serviço e selecione a conta do serviço em questão, assinalando a caixa de seleção. Agora o painel de informação deve ter ADD MEMBERbotão. Clique nele e cole o e-mail da conta de serviço para a New memberscaixa de texto. Clique no Select rolemenu suspenso e escolha o papel Service Accounts -> Service Account Token Creator. Você pode verificar que o papel é atribuído com o seguinte gcloudcomando:

gcloud iam service-accounts get-iam-policy [SERVICE_ACCOUNT_EMAIL]

Agora, para o código Python real. Este exemplo é uma ligeira modificação da documentação ligada acima.

from googleapiclient.discovery import build
from google.auth import default, iam
from google.auth.transport import requests
from google.oauth2 import service_account

TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'
SCOPES = ['https://www.googleapis.com/auth/admin.directory.user']
GSUITE_ADMIN_USER = 'admin@example.com'

def delegated_credentials(credentials, subject, scopes):
    try:
        # If we are using service account credentials from json file
        # this will work
        updated_credentials = credentials.with_subject(subject).with_scopes(scopes)
    except AttributeError:
        # This exception is raised if we are using GCE default credentials

        request = requests.Request()

        # Refresh the default credentials. This ensures that the information
        # about this account, notably the email, is populated.
        credentials.refresh(request)

        # Create an IAM signer using the default credentials.
        signer = iam.Signer(
            request,
            credentials,
            credentials.service_account_email
        )

        # Create OAuth 2.0 Service Account credentials using the IAM-based
        # signer and the bootstrap_credential's service account email.
        updated_credentials = service_account.Credentials(
            signer,
            credentials.service_account_email,
            TOKEN_URI,
            scopes=scopes,
            subject=subject
        )
    except Exception:
        raise

    return updated_credentials


creds, project = default()
creds = delegated_credentials(creds, GSUITE_ADMIN_USER, SCOPES) 

service = build('admin', 'directory_v1', credentials=creds)

O trybloco não irá falhar se você tiver GOOGLE_APPLICATION_CREDENTIALSset variável de ambiente com um caminho para um arquivo de conta de serviço. Se o aplicativo é executado no Google Cloud, haverá um AttributeErrore ele é tratado através da criação de novas credenciais que têm correta subjecte scopes.

Você também pode passar Nonecomo o subjectde delegated_credentialsfunção e cria as credenciais sem delegação de modo esta função pode ser usada com ou sem delegação.

Respondeu 18/07/2019 em 13:33
fonte usuário

votos
0

@ marc.fargas Você pode ter um olhar para os googleapis / google-auth-biblioteca-python biblioteca no GitHub. Você vai encontrar algumas informações relevantes para o método em questão:

As credenciais são consideradas imutáveis. Se você quiser modificar os escopos ou o assunto utilizado para delegação, uso: meth: with_scopesou: meth: with_subject:: scoped_credentials = credentials.with_scopes ([ 'email']) delegated_credentials = credentials.with_subject (sujeito)

Como você define a sua aplicação Credenciais padrão com "GOOGLE_APPLICATION_CREDENTIALS", que estava recebendo uma instância de google.auth.service_account.Credentials que tem o método with_subject.

Enquanto no App Engine, você está em vez recebendo uma instância de app_engine.Credentials , que não tem o método with_subject. Isso explica o comportamento observado eo erro que você vê.

De acordo com a documentação na delegação todo o domínio, única credenciais da conta de serviço pode ter delegação de todo o domínio.

Respondeu 14/11/2018 em 23:24
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more