Provider Setup¶
Getting Started walks the end-to-end console flow. This section is the per-provider companion: for every supported platform, the exact scopes and permissions the collector needs, the click-by-click steps to create the credential in that platform, the credential-secret format, and the first-run failures with their fixes.
It assumes the organization is already subscribed to the ext-cloud-security
extension (step 1 of
Getting Started).
Pick your platform¶
| Platform | Surface | What onboarding takes |
|---|---|---|
| Google Cloud | Cloud infra | Service account + Viewer & Security Reviewer at the org/folder/project |
| Amazon Web Services | Cloud infra | IAM user that assumes a read-only role, external-ID gated |
| Microsoft Azure | Cloud infra | App registration + Reader on the subscription + Graph consent |
| Microsoft Entra ID | Identity | App registration + Graph consent (directory only, no Azure needed) |
| Okta | Identity | API Services app (private-key JWT) + 5 read scopes + a read-only admin role |
| Google Workspace | Identity | Service account with domain-wide delegation impersonating a super admin |
| 1Password | Identity | SCIM bridge URL + bearer token (optionally a Connect server) |
| Auth0 | Identity | M2M application authorized on the Management API with read scopes |
| Cloudflare | SaaS | One scoped read-only API token + the account ID |
| GitHub | Source control | A GitHub App installed on the org, read-only by default (write access optional, for pull-request checks and AutoFix) |
| GitLab | Source control | A group/project access token with read_api + read_repository |
| Bitbucket Cloud | Source control | An Atlassian API token with three read scopes; the account must be a workspace member |
| OpenAI | AI | An Admin API key created with api.management.read |
| Anthropic | AI | A Console Admin key and/or an Enterprise Compliance key |
| LimaCharlie | LimaCharlie | An org or user API key with read permissions |
Connecting Providers is the conceptual overview of the same fifteen connectors — what each collects and why.
Use these guides with the wizard¶
Choose the service above and keep its guide open in a second browser tab. Each guide contains both setup instructions and technical reference material; you do not have to run its LimaCharlie CLI examples to use the web app.
- Check Prerequisites with your provider administrator. A read-only login for you personally may not be enough to create the application's credential.
- Follow the credential creation steps. Record the account/project/tenant IDs separately from the credential itself.
- In Cloud Security → Settings → Providers → Add provider, choose that service and enter those IDs under Configuration.
- Under Permissions, select New secret to store the credential, or select an existing saved secret. Follow the credential format for that service.
- Run Test Provider. Fix required failures; optional failures mean some data or capabilities will be unavailable.
- Save, wait for collection, and confirm a resource you recognize in Inventory. An accepted credential alone does not prove the intended account was scanned.
Choose browser steps or commands¶
Where a guide offers tabs, Web console walks through browser setup; Cloud Shell / CLI keeps the command alternative. Complete one method per step. You do not need to install a CLI to follow the browser instructions.
If you choose commands¶
The provider's CLI creates access in that provider. The limacharlie CLI
configures LimaCharlie. They are separate tools. If you use a provider command
block, install and sign in to that provider's CLI first and select the intended
account. Replace placeholders and define variables before running commands;
$SA_PROJECT, for example, means the project that owns a service account.
For Google Cloud you can use Cloud Shell in the Google Cloud console. For Azure, you can use Azure Cloud Shell. If you cannot create identities or grant roles, ask the provider administrator to perform those steps, then return to the wizard.
Advanced: the stored configuration¶
Every provider connection is two Hive records:
| Piece | Hive | Holds |
|---|---|---|
| Provider record | cloudsec_provider |
Non-secret config (scope, account/subscription IDs, regions) plus a reference to the credential. |
| Credential secret | secret |
The actual credential (key/token). Referenced from the provider record as hive://secret/<name> — never inlined. |
The full field reference for the provider record is in Configuration.
Store the credential first, then reference it. The secret record's value is the credential blob:
where secret.json is {"secret": "<the credential JSON, as a string>"}.
For secret set on stdin, install jq and build the envelope with jq -Rs.
credential.json below is the provider's credential JSON, with no outer
{"secret": …} envelope:
jq -Rs '{secret: .}' credential.json \
| limacharlie secret set --key <name> --enabled \
&& rm -f credential.json
Keep credentials out of command arguments
Use stdin as above, or --input-file with a prepared secret-record envelope.
--value exposes the expanded credential in process arguments; a literal
credential typed in the command also enters shell history. Remove temporary
credential copies after verifying the saved secret. File deletion is not a
guarantee of secure erasure on SSDs, snapshots, or backups.
Bare keys are accepted for single-key providers
For OpenAI, Anthropic, and LimaCharlie you may store the raw key string instead of a JSON object — it is wrapped into the documented shape automatically. Every other provider needs the JSON object exactly as its page documents.
Always preflight before saving¶
provider test connects with the credential ephemerally (it is never stored)
and probes every permission surface a sweep needs:
The response is a per-check report; each check carries id, name,
required, ok, and a human-readable detail. report.ok is the verdict
over the required checks only. A failed optional check means that surface
degrades gracefully — an inventory type goes unobserved — rather than the
connection failing, and its detail names exactly what you lose.
Every provider page lists its platform-specific check IDs and what each one means, on top of the two common checks below.
Once a record passes preflight, save it:
limacharlie hive set --hive-name cloudsec_provider --key <name> \
--input-file provider.yaml --enabled
In the web app
Everything here can also be done under Cloud Security → Settings → Providers → Add provider, with secrets managed under Organization Settings → Secrets Manager. The Test Provider button runs the same preflight.
The two checks every provider reports first¶
Before any provider-specific probe runs, the report always contains these two
required checks. They are identical for every connector, which is
why the per-provider tables in this section start at auth:
| Check | Required | Meaning if it fails |
|---|---|---|
config |
✅ | The provider record itself is malformed — a field required for this provider_type is missing or ill-formed (a scope that is not in the expected shape, an ARN that does not parse, and so on). Nothing is contacted. |
credential |
✅ | The hive://secret/<name> reference could not be resolved — no such secret, or it is disabled — or the secret's contents are not the JSON shape that provider documents. Nothing is contacted. |
Only once both pass does auth actually reach the platform.
Unknown fields on the provider record are rejected, not ignored
The provider record is parsed strictly, both by provider test and on
the Hive write: an unrecognized key is an error rather than something
silently dropped. A misspelled field name therefore fails outright, with the
offending key named, instead of quietly leaving a setting unapplied — use the
exact names from Configuration.
Credential secrets are not strict in the same way: an unrecognized key
there is dropped without complaint, which is why a mistyped credential field
surfaces later as an authentication failure instead. Each provider page
documents its exact credential keys.
Fields every provider accepts¶
| Field | Purpose |
|---|---|
internal_domains |
Your own email domains. A human identity outside them is classified external, and external access to sensitive resources is one of the highest-signal finding classes. The collector discovers the primary cloud-org domain by itself; secondary domains must be listed here or your own staff are falsely flagged external. |
refresh |
Re-enumeration cadence as a Go duration (6h, 24h). Minimum 5m; empty uses the service default. |
sync_now |
Any opaque value; changing it triggers an immediate re-sweep. |
feed_subscription |
Optional Pub/Sub subscription (projects/{p}/subscriptions/{s}) carrying a change feed, for seconds-latency updates between full sweeps. |
Principles that apply everywhere¶
- Read-only. Every credential documented here is read-only, except where a platform offers no read-only surface for something — those cases are called out explicitly on the provider's page. The one opt-in exception is GitHub, whose App can be granted write access for Code Security's pull-request checks and AutoFix pull requests.
- Least privilege. Grant the required set first, confirm with
provider test, then add optional grants only for the surfaces you want. - Nothing is stored inline. Credentials live in the
secrethive and are referenced. The provider record never holds key material, and credentials are never written to logs. - Partial grants are supported. A denied optional surface leaves that inventory type unobserved; it never fails the sweep or deletes previously-collected rows.
Credential-secret quick reference¶
| Provider | secret value |
|---|---|
| Google Cloud | The service-account key JSON |
| AWS | {"access_key_id": "...", "secret_access_key": "..."} |
| Azure | {"client_id": "...", "client_secret": "..."} |
| Entra ID | {"client_id": "...", "client_secret": "..."} |
| Okta | {"org_url": "...", "client_id": "...", "private_key": {…JWK…}}, or {"org_url": "...", "api_token": "..."} |
| Google Workspace | {"service_account_json": {…SA key…}, "admin_email": "...", "domain": "..."} |
| 1Password | {"scim_url": "...", "scim_token": "..."} (optional connect_url, connect_token) |
| Auth0 | {"client_id": "...", "client_secret": "..."} |
| Cloudflare | {"api_token": "..."} (optional user_api_token) |
| GitHub | {"private_key": "-----BEGIN RSA PRIVATE KEY-----…"} |
| OpenAI | {"admin_api_key": "sk-admin-..."} |
| Anthropic | {"admin_api_key": "sk-ant-admin01-..."} and/or {"compliance_api_key": "sk-ant-api01-..."} |
| LimaCharlie | {"api_key": "..."} |