Conectar su nubeConectar sua nuvem

El asistente de conexión guía por unos pocos pasos —se elige la nube, se define el alcance y el método, y conecta—. En todos, Cloura recibe credenciales de solo lectura: jamás pide permisos para modificar sus recursos.

O assistente de conexão guia por alguns poucos passos —escolhe sua nuvem, define o escopo e o método, e conecta—. Em todos, Cloura recebe credenciais somente leitura: nunca pede permissões para modificar seus recursos.

Dónde está·menú lateralOperaciónConexiones·El asistente se abre con Conectar proveedor cloud.

Onde fica·menu lateralOperaçãoConexões·O assistente é aberto com Conectar provedor cloud.

Solo lectura, siempre El asistente crea un rol/identidad de lectura (AWS ClouraReadOnly, Azure Reader, GCP WIF a un service account de lectura). Se revoca en cualquier momento, sin afectar la infraestructura.
Somente leitura, sempre O assistente cria um IAM Role/identidade de leitura (AWS ClouraReadOnly, Azure Reader, GCP WIF a um service account de leitura). Pode ser revogado a qualquer momento, sem afetar a infraestrutura.

Paso 1 — Elija su nubePasso 1 — Escolha sua nuvem

Abra Conexiones → Conectar proveedor cloud y seleccione el proveedor. El mismo asistente conecta AWS, Azure o GCP. El panel Seguro por diseño recuerda que el acceso es de solo lectura.

Abra Conexões → Conectar provedor cloud e selecione o provedor. O mesmo assistente conecta AWS, Azure ou GCP. O painel Seguro por design lembra que o acesso é somente leitura.

app.cloura.ai/onboarding
1 NubeNuvem 2 AlcanceEscopo 3 MétodoMétodo 4 ConectarConectar

Conexión del Proveedor CloudConexão do Provedor Cloud

Cloura necesita acceso de solo lectura para analizar su Proveedor Cloud. El mismo flujo conecta cualquier proveedor — elija uno y siga los pasos.

Cloura precisa de acesso somente leitura para analisar seu Provedor Cloud. O mesmo fluxo conecta qualquer provedor — escolha um e siga os passos.

Paso 1 del asistente real: elegir el proveedor.
Passo 1 do assistente real: escolher o provedor.

Paso 2 — Alcance y métodoPasso 2 — Escopo e método

Elija el alcance (una cuenta individual o toda su organización) y el método de conexión: una guía paso a paso por la consola de su nube, o unos comandos de CLI. Ambos crean exactamente el mismo acceso de solo lectura.

Escolha o escopo (uma conta individual ou toda a sua organização) e o método de conexão: um guia passo a passo pelo console da sua nuvem, ou alguns comandos de CLI. Ambos criam exatamente o mesmo acesso somente leitura.

app.cloura.ai/onboarding
1 NubeNuvem 2 AlcanceEscopo 3 MétodoMétodo 4 ConectarConectar
AWSAWS · IndividualAWS · Individual

Elija el método de conexiónEscolha o método de conexão

Paso de método: "Guía por consola" o "CLI" — ambos otorgan solo lectura.
Passo de método: "Guia por console" ou "CLI" — ambos concedem somente leitura.

Paso 3 — Conecte en solo lecturaPasso 3 — Conecte em somente leitura

Copie el ExternalId que entrega Cloura, cree el rol ClouraReadOnly (política administrada ReadOnlyAccess) con confianza hacia Cloura y pegue su ARN. Pulse Verificar conexión: si el acceso es válido, la cuenta queda lista para el primer análisis. Ninguna acción de escritura está incluida.

Copie o ExternalId que a Cloura entrega, crie o IAM Role ClouraReadOnly (política gerenciada ReadOnlyAccess) com confiança para a Cloura e cole o seu ARN. Pressione Verificar conexão: se o acesso for válido, a conta fica pronta para a primeira análise. Nenhuma ação de escrita está incluída.

Antes de crear el rol, el equipo de seguridad suele pedir el detalle: qué permisos exactos recibe Cloura en cada nube, desde qué identidad se conecta y cómo se revoca el acceso. Está documentado en Confianza y seguridad.

Antes de criar o papel, a equipe de segurança costuma pedir o detalhe: quais permissões exatas a Cloura recebe em cada nuvem, de qual identidade se conecta e como o acesso é revogado. Está documentado em Confiança e segurança.

app.cloura.ai/onboarding
1 NubeNuvem 2 AlcanceEscopo 3 MétodoMétodo 4 ConectarConectar
AWSAWS · Guía por consolaAWS · Guia por console

Conexión del Proveedor CloudConexão do Provedor Cloud

Conecte una cuenta en modo solo lectura. El mismo flujo conecta cualquier Proveedor Cloud — elija uno y siga los pasos.

Conecta uma conta em modo somente leitura. O mesmo fluxo conecta qualquer Provedor Cloud — escolha um e siga os passos.

ExternalId cloura-7f3a9c2e-ana-rios-prod
Esperando credencialesAguardando credenciais
Paso final: ExternalId, ARN del rol de solo lectura y "Verificar conexión".
Passo final: ExternalId, ARN do IAM Role de somente leitura e "Verificar conexão".

Guías por proveedorGuias por provedor

El asistente ejecuta todo esto por usted y rellena los valores (ExternalId, subject de federación) automáticamente. Para hacerlo a mano, aquí está por cada nube la conexión de una cuenta con CLI y la de toda la organización (multi-cuenta).

O assistente executa tudo isto e preenche os valores (ExternalId, subject de federação) automaticamente. Para fazê-lo à mão, aqui está para cada nuvem a conexão de uma conta com CLI e a de toda a organização (multi-conta).

Cada script se comprueba a sí mismoAl terminar, el script verifica los permisos que realmente quedaron y solo entonces imprime la línea que se pega en Cloura. Si algo faltó —una asignación de permisos puede tardar unos segundos en propagar—, en vez de esa línea imprime NO QUEDO LISTO, qué falta y el comando exacto para completarlo. En ese caso no pegue nada en Cloura: ejecute lo que indica y vuelva a correr el script, que es idempotente y se puede repetir sin riesgo.
Cada script se verifica sozinhoAo terminar, o script confere as permissões que de fato ficaram e só então imprime a linha que se cola na Cloura. Se algo faltou —uma atribuição de permissões pode levar alguns segundos para propagar—, em vez dessa linha imprime NO QUEDO LISTO, o que falta e o comando exato para completar. Nesse caso não cole nada na Cloura: execute o que ele indica e rode o script de novo, que é idempotente e pode ser repetido sem risco.

AWS Amazon Web Services

Conexión por rol de solo lectura (ClouraReadOnly con la política administrada ReadOnlyAccess), que Cloura asume mediante un ExternalId.

Conexão por IAM Role de somente leitura (ClouraReadOnly com a política gerenciada ReadOnlyAccess), que Cloura assume por meio de um ExternalId.

Cuenta individual (CLI)Conta individual (CLI)

Ejecútelo con el aws-cli autenticado en la cuenta que quiere conectar. Crea el rol, le adjunta ReadOnlyAccess e imprime el ARN para pegarlo en Cloura.

Execute-o com o aws-cli autenticado na conta a conectar. Cria o IAM Role, anexa ReadOnlyAccess e imprime o ARN para colá-lo na Cloura.

Alternativa sin instalar nada: AWS CloudShellEl mismo script se puede pegar en AWS CloudShell abierto en la cuenta que quiere conectar (icono de terminal, arriba a la derecha de la consola de AWS). Ya viene con aws-cli autenticado.
Alternativa sem instalar nada: AWS CloudShellO mesmo script pode ser colado no AWS CloudShell aberto na conta a conectar (ícone de terminal, no canto superior direito do console da AWS). Já vem com aws-cli autenticado.
terminal · aws-cli
export AWS_PAGER=""

TRUST='{
  "Version":"2012-10-17",
  "Statement":[{
    "Effect":"Allow",
    "Principal":{"AWS":"arn:aws:iam::183124052250:root"},
    "Action":"sts:AssumeRole",
    "Condition":{"StringEquals":{"sts:ExternalId":"cloura-7f3a9c2e"}}
  }]
}'

aws iam create-role --role-name ClouraReadOnly \
  --assume-role-policy-document "$TRUST" 2>/dev/null ||
aws iam update-assume-role-policy --role-name ClouraReadOnly \
  --policy-document "$TRUST"

aws iam attach-role-policy --role-name ClouraReadOnly \
  --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

echo "Add-on Costos Kubernetes: si lo contrato, reemplace MI_BUCKET_CUR por el bucket de su export CUR 2.0."
echo "Sin comodines: cada accion queda atada al workgroup, al catalogo y al bucket de SU cuenta."
echo "La UNICA escritura es athena-results/, los resultados de la propia consulta."
ACCT=$(aws sts get-caller-identity --query Account --output text)

CURPOL='{
  "Version":"2012-10-17",
  "Statement":[
    {"Effect":"Allow","Action":["athena:StartQueryExecution","athena:GetQueryExecution","athena:GetQueryResults"],"Resource":"arn:aws:athena:us-east-1:'"$ACCT"':workgroup/primary"},
    {"Effect":"Allow","Action":["glue:GetDatabase","glue:GetDatabases","glue:GetTable","glue:GetTables","glue:GetPartitions"],"Resource":["arn:aws:glue:us-east-1:'"$ACCT"':catalog","arn:aws:glue:us-east-1:'"$ACCT"':database/*","arn:aws:glue:us-east-1:'"$ACCT"':table/*/*"]},
    {"Effect":"Allow","Action":["s3:GetObject","s3:ListBucket"],"Resource":["arn:aws:s3:::MI_BUCKET_CUR","arn:aws:s3:::MI_BUCKET_CUR/*"]},
    {"Effect":"Allow","Action":"s3:PutObject","Resource":"arn:aws:s3:::MI_BUCKET_CUR/athena-results/*"}
  ]
}'
if echo "$CURPOL" | grep -q MI_BUCKET_CUR; then
  echo "Se omite el grant del add-on Costos Kubernetes: falta indicar su bucket CUR."
else
  aws iam put-role-policy --role-name ClouraReadOnly \
    --policy-name ClouraK8sCostCUR --policy-document "$CURPOL"
fi
ROLE_ARN=$(aws iam get-role --role-name ClouraReadOnly --query Role.Arn --output text 2>/dev/null)
if [ -z "$ROLE_ARN" ]; then
  echo "NO QUEDO LISTO: no existe el rol ClouraReadOnly."
  exit 1
fi
if ! aws iam list-attached-role-policies --role-name ClouraReadOnly --query "AttachedPolicies[?PolicyName=='ReadOnlyAccess'] | [0].PolicyName" --output text 2>/dev/null | grep -q ReadOnlyAccess; then
  echo "NO QUEDO LISTO: al rol ClouraReadOnly le falta la politica ReadOnlyAccess."
  echo "Ejecute esto y vuelva a correr el script:"
  echo "  aws iam attach-role-policy --role-name ClouraReadOnly --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess"
  exit 1
fi

echo "$ROLE_ARN"
Solo lecturaLa política ReadOnlyAccess es de AWS y no permite ningún cambio. El ExternalId y el valor de ID_CUENTA_CLOURA los entrega el asistente ya personalizados en el paso Conectar; reemplácelos antes de ejecutar el comando. ¿Su equipo de seguridad necesita el detalle del acceso —qué alcanza cada rol, qué queda fuera y cómo se revoca—? Está en Confianza y seguridad.
Somente leituraA política ReadOnlyAccess é da AWS e não permite nenhuma alteração. O ExternalId e o valor de ID_CUENTA_CLOURA são entregues pelo assistente já personalizados no passo Conectar; substitua-os antes de executar o comando. A sua equipe de segurança precisa do detalhe do acesso —o que cada papel alcança, o que fica de fora e como se revoga—? Está em Confiança e segurança.

Organización completa (multi-cuenta)Organização completa (multi-conta)

Se apoya en dos roles: (1) ClouraOrgReadOnly en la cuenta de gestión (management/payer), que Cloura asume para listar las cuentas (organizations:ListAccounts); y (2) ClouraReadOnly en cada cuenta miembro (despliéguelo con un StackSet usando el mismo trust). Ejecute este script en la cuenta de gestión y pegue el ARN que imprime:

Apoia-se em dois IAM Roles: (1) ClouraOrgReadOnly na conta de gestão (management/payer), que Cloura assume para listar as contas (organizations:ListAccounts); e (2) ClouraReadOnly em cada conta membro (implante-o com um StackSet usando o mesmo trust). Execute este script na conta de gestão e cola o ARN que ele imprime:

Alternativa: AWS CloudShellTambién se puede ejecutar desde AWS CloudShell abierto en la cuenta de gestión (management/payer) de la organización — es la cuenta donde se crea ClouraOrgReadOnly. El rol ClouraReadOnly de cada cuenta miembro se despliega aparte con el StackSet.
Alternativa: AWS CloudShellVocê também pode executá-lo a partir do AWS CloudShell aberto na conta de gestão (management/payer) da organização — é a conta onde se cria ClouraOrgReadOnly. O IAM Role ClouraReadOnly de cada conta membro se implanta à parte com o StackSet.
cloura-org-aws.sh
export AWS_PAGER=""

TRUST='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::183124052250:root"},"Action":"sts:AssumeRole","Condition":{"StringEquals":{"sts:ExternalId":"cloura-7f3a9c2e"}}}]}'

aws iam create-role --role-name ClouraOrgReadOnly \
  --assume-role-policy-document "$TRUST" 2>/dev/null ||
aws iam update-assume-role-policy --role-name ClouraOrgReadOnly \
  --policy-document "$TRUST"

aws iam attach-role-policy --role-name ClouraOrgReadOnly \
  --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess


ROLE_ARN=$(aws iam get-role --role-name ClouraOrgReadOnly --query Role.Arn --output text 2>/dev/null)
if [ -z "$ROLE_ARN" ]; then
  echo "NO QUEDO LISTO: no existe el rol ClouraOrgReadOnly."
  exit 1
fi
if ! aws iam list-attached-role-policies --role-name ClouraOrgReadOnly --query "AttachedPolicies[?PolicyName=='ReadOnlyAccess'] | [0].PolicyName" --output text 2>/dev/null | grep -q ReadOnlyAccess; then
  echo "NO QUEDO LISTO: al rol ClouraOrgReadOnly le falta la politica ReadOnlyAccess."
  echo "Ejecute esto y vuelva a correr el script:"
  echo "  aws iam attach-role-policy --role-name ClouraOrgReadOnly --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess"
  exit 1
fi

echo "$ROLE_ARN"
Dos piezasEl ARN que pega es el de la cuenta de gestión (lista las cuentas). Cada cuenta miembro necesita además su propio rol ClouraReadOnly de solo lectura vía StackSet.
Duas peçasO ARN colado é o da conta de gestão (lista as contas). Cada conta membro precisa, além disso, do seu próprio IAM Role ClouraReadOnly de somente leitura via StackSet.

AZ Microsoft Azure

Conexión por federación de identidad (OIDC): una App Registration con credencial federada y los roles Reader + Cost Management Reader. Sin secretos que rotar.

Conexão por federação de identidade (OIDC): uma App Registration com credencial federada e os roles Reader + Cost Management Reader. Sem segredos para rotacionar.

Suscripción individual (CLI)Assinatura individual (CLI)

Ejecútelo con az autenticado en la suscripción a conectar. Crea o reutiliza la App Cloura-ReadOnly, agrega la credencial federada, asigna los roles de lectura e imprime tenant / subscription / client.

Execute-o com o az autenticado na assinatura a conectar. Cria ou reutiliza a App Cloura-ReadOnly, adiciona a credencial federada, atribui os roles de leitura e imprime tenant / subscription / client.

Alternativa sin instalar nada: Azure Cloud ShellEl script se puede pegar en Azure Cloud Shell con la suscripción a conectar activa (az account set --subscription <id>). Ya trae az autenticado.
Alternativa sem instalar nada: Azure Cloud ShellO script pode ser colado no Azure Cloud Shell com a assinatura a conectar ativa (az account set --subscription <id>). Já traz o az autenticado.
terminal · az-cli
SUB_ID=$(az account show --query id -o tsv)

APP_ID=$(az ad app list --display-name Cloura-ReadOnly --query "[0].appId" -o tsv)
[ -z "$APP_ID" ] && APP_ID=$(az ad app create --display-name Cloura-ReadOnly --query appId -o tsv)

az ad sp show --id "$APP_ID" >/dev/null 2>&1 || az ad sp create --id "$APP_ID" >/dev/null

echo "Esperando a que la identidad quede disponible..."
SP_ID=""
for i in 1 2 3 4 5 6 7 8 9 10; do
  SP_ID=$(az ad sp show --id "$APP_ID" --query id -o tsv 2>/dev/null)
  [ -n "$SP_ID" ] && break
  sleep 3
done
if [ -z "$SP_ID" ]; then
  echo "NO QUEDO LISTO: la aplicacion $APP_ID todavia no esta disponible."
  echo "Espere un minuto y vuelva a ejecutar este mismo script."
  exit 1
fi

FC_JSON='{"name":"cloura-oidc","issuer":"https://api.cloura.ai/oidc","subject":"<CLOURA_SUBJECT>","audiences":["api://AzureADTokenExchange"]}'
FC_SUBJECT=$(az ad app federated-credential list --id "$APP_ID" --query "[?name=='cloura-oidc'] | [0].subject" -o tsv)
if [ -z "$FC_SUBJECT" ]; then
  az ad app federated-credential create --id "$APP_ID" --parameters "$FC_JSON" >/dev/null
elif [ "$FC_SUBJECT" != "<CLOURA_SUBJECT>" ]; then
  az ad app federated-credential update --id "$APP_ID" --federated-credential-id cloura-oidc --parameters "$FC_JSON" >/dev/null
fi

for ROLE in Reader "Cost Management Reader"; do
  if ! az role assignment list --assignee "$APP_ID" --role "$ROLE" --scope "/subscriptions/$SUB_ID" --query "[0].id" -o tsv | grep -q .; then
    for i in 1 2 3 4 5; do
      az role assignment create --assignee-object-id "$SP_ID" --assignee-principal-type ServicePrincipal --role "$ROLE" --scope "/subscriptions/$SUB_ID" >/dev/null 2>&1 && break
      sleep 3
    done
  fi
done

FALTA=0
for ROLE in Reader "Cost Management Reader"; do
  if ! az role assignment list --assignee "$APP_ID" --role "$ROLE" --scope "/subscriptions/$SUB_ID" --query "[0].id" -o tsv | grep -q .; then
    [ "$FALTA" = "0" ] && echo "NO QUEDO LISTO. Falta:"
    FALTA=1
    echo "  el rol $ROLE en la subscription"
  fi
done
FC_OK=$(az ad app federated-credential list --id "$APP_ID" --query "[?name=='cloura-oidc'] | [0].subject" -o tsv)
if [ "$FC_OK" != "<CLOURA_SUBJECT>" ]; then
  [ "$FALTA" = "0" ] && echo "NO QUEDO LISTO. Falta:"
  FALTA=1
  echo "  la credencial federada cloura-oidc"
fi
if [ "$FALTA" = "1" ]; then
  echo "Compruebe que su usuario pueda asignar roles en la subscription y vuelva a ejecutar este script."
  exit 1
fi

echo "Pega en Cloura: tenant=$(az account show --query tenantId -o tsv) subscription=$SUB_ID client=$APP_ID"
Solo lecturaReader y Cost Management Reader son roles de consulta. El subject de federación lo entrega el asistente.
Somente leituraReader e Cost Management Reader são roles de consulta. O subject de federação é entregue pelo assistente.

Todas las suscripciones (organización)Todas as assinaturas (organização)

El mismo enfoque, asignando los roles de lectura a todas las suscripciones del tenant en un solo script. No necesita Management Group ni permisos especiales; al terminar pegue tenant=… client=….

O mesmo enfoque, atribuindo os roles de leitura a todas as assinaturas do tenant num único script. Você não precisa de Management Group nem permissões especiais; ao terminar cola tenant=… client=….

Alternativa: Azure Cloud ShellSe puede correr desde Azure Cloud Shell autenticado en el tenant, con una identidad que pueda asignar roles en las suscripciones (por ejemplo User Access Administrator u Owner).
Alternativa: Azure Cloud ShellPode ser executado a partir do Azure Cloud Shell autenticado no tenant, com uma identidade que possa atribuir roles nas assinaturas (por exemplo User Access Administrator ou Owner).
cloura-org-azure.sh
TENANT_ID=$(az account show --query tenantId -o tsv)
APP_ID=$(az ad app list --display-name Cloura-ReadOnly --query "[0].appId" -o tsv)
[ -z "$APP_ID" ] && APP_ID=$(az ad app create --display-name Cloura-ReadOnly --query appId -o tsv)
az ad sp show --id "$APP_ID" >/dev/null 2>&1 || az ad sp create --id "$APP_ID" >/dev/null
echo "Esperando a que la identidad quede disponible..."
SP_ID=""
for i in 1 2 3 4 5 6 7 8 9 10; do
  SP_ID=$(az ad sp show --id "$APP_ID" --query id -o tsv 2>/dev/null)
  [ -n "$SP_ID" ] && break
  sleep 3
done
if [ -z "$SP_ID" ]; then
  echo "NO QUEDO LISTO: la aplicacion $APP_ID todavia no esta disponible."
  echo "Espere un minuto y vuelva a ejecutar este mismo script."
  exit 1
fi
FC_JSON='{"name":"cloura-oidc","issuer":"https://api.cloura.ai/oidc","subject":"<CLOURA_SUBJECT>","audiences":["api://AzureADTokenExchange"]}'
FC_SUBJECT=$(az ad app federated-credential list --id "$APP_ID" --query "[?name=='cloura-oidc'] | [0].subject" -o tsv)
if [ -z "$FC_SUBJECT" ]; then
  az ad app federated-credential create --id "$APP_ID" --parameters "$FC_JSON" >/dev/null
elif [ "$FC_SUBJECT" != "<CLOURA_SUBJECT>" ]; then
  az ad app federated-credential update --id "$APP_ID" --federated-credential-id cloura-oidc --parameters "$FC_JSON" >/dev/null
fi

for SUB in $(az account list --query "[?tenantId=='$TENANT_ID'].id" -o tsv); do
  for ROLE in Reader "Cost Management Reader"; do
    az role assignment list --assignee "$APP_ID" --role "$ROLE" --scope "/subscriptions/$SUB" --query "[0].id" -o tsv | grep -q . ||
    az role assignment create --assignee-object-id "$SP_ID" --assignee-principal-type ServicePrincipal --role "$ROLE" --scope "/subscriptions/$SUB" >/dev/null
  done
done

FALTA=0
for SUB in $(az account list --query "[?tenantId=='$TENANT_ID'].id" -o tsv); do
  for ROLE in Reader "Cost Management Reader"; do
    if ! az role assignment list --assignee "$APP_ID" --role "$ROLE" --scope "/subscriptions/$SUB" --query "[0].id" -o tsv | grep -q .; then
      [ "$FALTA" = "0" ] && echo "NO QUEDO LISTO. Falta:"
      FALTA=1
      echo "  el rol $ROLE en la subscription $SUB"
    fi
  done
done
if [ "$FALTA" = "1" ]; then
  echo "Compruebe que su usuario pueda asignar roles en esas suscripciones y vuelva a ejecutar este script."
  exit 1
fi

echo "Pega en Cloura: tenant=$TENANT_ID client=$APP_ID"

GCP Google Cloud

Conexión por Workload Identity Federation (WIF): un pool OIDC y una service account cloura-readonly con roles de solo lectura (viewer, cloudasset.viewer, etc.).

Conexão por Workload Identity Federation (WIF): um pool OIDC e uma service account cloura-readonly com roles de somente leitura (viewer, cloudasset.viewer, etc.).

Proyecto individual (CLI)Projeto individual (CLI)

Ejecútelo con gcloud autenticado en el proyecto. Crea el WIF pool, el provider OIDC y la service account, le da los roles de lectura e imprime wif / service / project.

Execute-o com o gcloud autenticado no projeto. Cria o WIF pool, o provider OIDC e a service account, concede os roles de leitura e imprime wif / service / project.

Alternativa sin instalar nada: Cloud Shell de GCPEl script se puede pegar en Cloud Shell con el proyecto a conectar activo (gcloud config set project <id>). Ya trae gcloud autenticado.
Alternativa sem instalar nada: Cloud Shell do GCPO script pode ser colado no Cloud Shell com o projeto a conectar ativo (gcloud config set project <id>). Já traz o gcloud autenticado.
terminal · gcloud
PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
CLOURA_SUBJECT="<CLOURA_SUBJECT>"
SA=cloura-readonly@$PROJECT_ID.iam.gserviceaccount.com
ROLES="roles/viewer roles/cloudasset.viewer roles/iam.securityReviewer roles/recommender.viewer roles/monitoring.viewer"

POOL_STATE=$(gcloud iam workload-identity-pools describe cloura-pool --location=global --project=$PROJECT_ID --format="value(state)" 2>/dev/null)
if [ "$POOL_STATE" = "DELETED" ]; then
  echo "El pool existia borrado (GCP lo guarda 30 dias). Restaurandolo."
  gcloud iam workload-identity-pools undelete cloura-pool --location=global --project=$PROJECT_ID
elif [ -z "$POOL_STATE" ]; then
  gcloud iam workload-identity-pools create cloura-pool --location=global --project=$PROJECT_ID
fi

PROV_STATE=$(gcloud iam workload-identity-pools providers describe cloura-oidc --location=global --workload-identity-pool=cloura-pool --project=$PROJECT_ID --format="value(state)" 2>/dev/null)
if [ "$PROV_STATE" = "DELETED" ]; then
  gcloud iam workload-identity-pools providers undelete cloura-oidc --location=global --workload-identity-pool=cloura-pool --project=$PROJECT_ID
elif [ -z "$PROV_STATE" ]; then
  gcloud iam workload-identity-pools providers create-oidc cloura-oidc \
    --location=global --workload-identity-pool=cloura-pool --project=$PROJECT_ID \
    --issuer-uri="https://api.cloura.ai/oidc" --attribute-mapping="google.subject=assertion.sub"
fi

gcloud iam service-accounts describe $SA --project=$PROJECT_ID >/dev/null 2>&1 \
  || gcloud iam service-accounts create cloura-readonly --project=$PROJECT_ID

echo "Esperando a que la cuenta de servicio quede disponible..."
SA_OK=""
for i in 1 2 3 4 5 6 7 8 9 10; do
  gcloud iam service-accounts describe $SA --project=$PROJECT_ID >/dev/null 2>&1 && { SA_OK=1; break; }
  sleep 3
done
if [ -z "$SA_OK" ]; then
  echo "NO QUEDO LISTO: la cuenta de servicio $SA todavia no esta disponible."
  echo "Espere un minuto y vuelva a ejecutar este mismo script."
  exit 1
fi

for R in $ROLES; do
  for i in 1 2 3 4 5; do
    gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:$SA" --role="$R" >/dev/null 2>&1 && break
    sleep 3
  done
done

BA=$(gcloud billing projects describe $PROJECT_ID --format="value(billingAccountName)" 2>/dev/null)
[ -n "$BA" ] && gcloud billing accounts add-iam-policy-binding ${BA#billingAccounts/} --member="serviceAccount:$SA" --role="roles/billing.viewer" >/dev/null 2>&1

PNUM=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
gcloud iam service-accounts add-iam-policy-binding $SA --role=roles/iam.workloadIdentityUser \
  --member="principal://iam.googleapis.com/projects/$PNUM/locations/global/workloadIdentityPools/cloura-pool/subject/$CLOURA_SUBJECT" >/dev/null

FALTAN=""
CONCEDIDOS=$(gcloud projects get-iam-policy $PROJECT_ID --flatten="bindings[].members" --filter="bindings.members:serviceAccount:$SA" --format="value(bindings.role)" 2>/dev/null)
for R in $ROLES; do
  echo "$CONCEDIDOS" | grep -Fqx "$R" || FALTAN="$FALTAN $R"
done
if [ -n "$FALTAN" ]; then
  echo ""
  echo "NO QUEDO LISTO. Faltan estos permisos de solo lectura:"
  for R in $FALTAN; do echo "  $R"; done
  echo ""
  echo "Ejecute estas lineas y vuelva a correr el script:"
  for R in $FALTAN; do echo "  gcloud projects add-iam-policy-binding $PROJECT_ID --member=\"serviceAccount:$SA\" --role=\"$R\""; done
  exit 1
fi

echo "Pega en Cloura: wif=//iam.googleapis.com/projects/$PNUM/locations/global/workloadIdentityPools/cloura-pool/providers/cloura-oidc service=$SA project=$PROJECT_ID"
Solo lecturaTodos los roles son de consulta; cloudasset.viewer es obligatorio para el descubrimiento de recursos.
Somente leituraTodos os roles são de consulta; cloudasset.viewer é obrigatório para o descobrimento de recursos.

Organización completaOrganização completa

Primero ejecute la conexión del proyecto individual (crea cloura-pool y la service account). Luego otorgue el rol roles/browser a nivel de organización para descubrir todos los proyectos; pegue org=… wif=… service=….

Primeiro execute a conexão do projeto individual (cria cloura-pool e a service account). Depois concede o role roles/browser a nível de organização para descobrir todos os projetos; cola org=… wif=… service=….

Alternativa: Cloud Shell de GCPTambién se puede ejecutar desde Cloud Shell, con una identidad que tenga permisos de IAM a nivel de organización (para conceder roles/browser en la organización).
Alternativa: Cloud Shell do GCPVocê também pode executá-lo a partir do Cloud Shell, com uma identidade que tenha permissões de IAM a nível de organização (para conceder roles/browser na organização).
cloura-org-gcp.sh
PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
PNUM=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
SA=cloura-readonly@$PROJECT_ID.iam.gserviceaccount.com
ORG_ID=$(gcloud organizations list --format="value(name.basename())" | head -1)

gcloud organizations add-iam-policy-binding $ORG_ID --member="serviceAccount:$SA" --role="roles/browser" >/dev/null

if [ -z "$ORG_ID" ]; then
  echo "NO QUEDO LISTO: no se encontro ninguna organizacion con este usuario."
  echo "Compruebe con: gcloud organizations list"
  exit 1
fi
if ! gcloud organizations get-iam-policy $ORG_ID --flatten="bindings[].members" --filter="bindings.members:serviceAccount:$SA" --format="value(bindings.role)" 2>/dev/null | grep -Fqx "roles/browser"; then
  echo "NO QUEDO LISTO: falta roles/browser para $SA en la organizacion $ORG_ID."
  echo "Ejecute esto y vuelva a correr el script:"
  echo "  gcloud organizations add-iam-policy-binding $ORG_ID --member=\"serviceAccount:$SA\" --role=\"roles/browser\""
  exit 1
fi

echo "Pega en Cloura: org=$ORG_ID wif=//iam.googleapis.com/projects/$PNUM/locations/global/workloadIdentityPools/cloura-pool/providers/cloura-oidc service=$SA"