mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-17 08:54:16 +00:00
feat(azure): clarify certificate onboarding permissions and trim wizard copy
This commit is contained in:
1 parent
844f766c8f
commit
0f778b0862
4 files changed
+67
-30
No files matched your search
@@ -231,12 +231,43 @@ Certificate authentication is the recommended way to run Prowler against Azure b
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Certificate authentication requires:
|
||||
Certificate authentication touches two separate permission systems: **Microsoft Entra ID** (identity) and **Azure RBAC** (subscription). Both are required.
|
||||
|
||||
- Permission to create or manage a Microsoft Entra App Registration.
|
||||
- An administrator authorized to grant tenant-wide consent for the required Microsoft Graph application permissions.
|
||||
- `Owner` on each target subscription when using the deployment template. `Contributor` cannot create role definitions or role assignments.
|
||||
- The Service Principal Object ID from **Microsoft Entra ID** > **Enterprise applications** > the application > **Overview**. This value differs from the Object ID under **App registrations**.
|
||||
#### Microsoft Entra ID roles per setup step
|
||||
|
||||
| Setup step | Minimum role required |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **1. Register a new App Registration** | Any member user, _by default_. Member users can register applications through the built-in default user permissions. If the tenant disabled this by setting _Users can register applications_ to **No** (under **Microsoft Entra ID** > **Users** > **User settings**), the user needs one of: `Application Administrator`, `Cloud Application Administrator`, or `Global Administrator`. |
|
||||
| **2. Upload the certificate to the App Registration** | The App Registration's owner (the user who created it, added automatically) — or `Application Administrator`, `Cloud Application Administrator`, or `Global Administrator`. |
|
||||
| **3. Add Microsoft Graph _application_ permissions (request)** — `AuditLog.Read.All`, `Directory.Read.All`, `Policy.Read.All` | The App Registration's owner — or `Application Administrator`, `Cloud Application Administrator`, or `Global Administrator`. Requesting a permission and granting consent are separate operations; see step 4 for the consent role. |
|
||||
| **4. Grant tenant-wide admin consent for those permissions** ⚠️ | **`Global Administrator`** or **`Privileged Role Administrator`** _only_. `Application Administrator`, `Cloud Application Administrator`, and `AI Administrator` **cannot** consent to _Microsoft Graph_ application permissions — they can consent to application permissions for other APIs, but not Microsoft Graph app roles, per [Microsoft's admin consent documentation](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/grant-admin-consent#prerequisites) and [Microsoft Graph permissions overview](https://learn.microsoft.com/en-us/graph/permissions-overview). |
|
||||
| **5. Read the Service Principal Object ID from Enterprise applications** | Any signed-in user (read-only, granted by default user permissions). |
|
||||
|
||||
The Service Principal Object ID lives on **Microsoft Entra ID** > **Enterprise applications** > _the application_ > **Overview**. This value is different from the Object ID that appears under **App registrations** for the same application; both objects share the same Application (client) ID but each has its own Object ID.
|
||||
|
||||
#### Azure RBAC role for the subscription template
|
||||
|
||||
The Deploy to Azure template creates one custom role definition and two role assignments (`Reader` and the custom `ProwlerRole`) at subscription scope. The account that runs the deployment needs one of:
|
||||
|
||||
- **`Owner`** on the target subscription. Simplest and most common. `Owner` grants both `Microsoft.Authorization/roleDefinitions/write` and `Microsoft.Authorization/roleAssignments/write`.
|
||||
- Alternatively, **`Contributor` combined with `User Access Administrator`** on the target subscription. `Contributor` alone is not enough because it explicitly cannot create role assignments (see [Azure built-in roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles)); `User Access Administrator` fills the gap for role definitions and role assignments.
|
||||
|
||||
<Note>
|
||||
**Global Administrator does not automatically have Azure RBAC.** Per
|
||||
[Microsoft's Elevate access
|
||||
documentation](https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin):
|
||||
"As a Global Administrator in Microsoft Entra ID, you might not have access to
|
||||
all subscriptions and management groups in your tenant." To grant a Global
|
||||
Administrator temporary access, open **Microsoft Entra ID** > **Properties**
|
||||
and set **Access management for Azure resources** to **Yes**. This assigns
|
||||
`User Access Administrator` at root scope (`/`), which covers step 6. Disable
|
||||
the toggle after the setup is done — the assignment persists per-user until
|
||||
revoked.
|
||||
</Note>
|
||||
|
||||
#### Shortest single-user path
|
||||
|
||||
The simplest way for one user to complete the whole flow is **`Global Administrator`** in Microsoft Entra ID (covers steps 1-4 by inclusion) combined with the Elevate access toggle above (covers step 6). Deploying with a least-privilege split (for example, an `Application Administrator` for step 1-3, a `Privileged Role Administrator` for step 4, and an `Owner` for step 6) is also supported.
|
||||
|
||||
### Generating the Certificate
|
||||
|
||||
|
||||
Binary file not shown.
+6
-6
@@ -103,22 +103,22 @@ describe("AzureCertificateCredentialsForm", () => {
|
||||
const steps = screen.getAllByRole("listitem");
|
||||
expect(steps).toHaveLength(6);
|
||||
expect(steps[0]).toHaveTextContent(
|
||||
"Register an Azure application, then copy its Directory (tenant) ID and Application (client) ID.",
|
||||
"Register an Azure application. From its Overview page, copy the Directory (tenant) ID and Application (client) ID.",
|
||||
);
|
||||
expect(steps[1]).toHaveTextContent(
|
||||
"Generate the certificate. The private bundle is filled below and submitted to Prowler only when you connect.",
|
||||
"Generate a certificate. The private bundle fills the field below and prowler-cert.cer downloads for step 3.",
|
||||
);
|
||||
expect(steps[2]).toHaveTextContent(
|
||||
"Upload prowler-cert.cer under Certificates & secrets. Add Microsoft Graph application permissions: AuditLog.Read.All, Directory.Read.All (or Domain.Read.All), and Policy.Read.All. Then grant admin consent.",
|
||||
"In your App Registration, upload prowler-cert.cer under Certificates & secrets. Then in API permissions, add the Microsoft Graph application permissions AuditLog.Read.All, Directory.Read.All, and Policy.Read.All, and click Grant admin consent.",
|
||||
);
|
||||
expect(steps[3]).toHaveTextContent(
|
||||
"Copy the Service Principal Object ID from Enterprise applications.",
|
||||
"Open Enterprise applications, select the same app, and copy its Object ID (different from the App Registration's Object ID).",
|
||||
);
|
||||
expect(steps[4]).toHaveTextContent(
|
||||
"Deploy subscription RBAC with the Service Principal Object ID. The template creates ProwlerRole and assigns Reader and ProwlerRole; it does not create Entra resources.",
|
||||
"Deploy the template with the Service Principal Object ID from step 4. It grants Reader and a custom ProwlerRole on the subscription.",
|
||||
);
|
||||
expect(steps[5]).toHaveTextContent(
|
||||
"Return to Prowler and complete the fields below. The generated certificate bundle is already filled.",
|
||||
"Return to Prowler and paste the Tenant ID and Client ID from step 1 into the fields below. The certificate field is already filled.",
|
||||
);
|
||||
expect(
|
||||
screen.getByRole("textbox", {
|
||||
|
||||
+25
-19
@@ -73,8 +73,10 @@ export const AzureCertificateCredentialsForm = ({
|
||||
Certificate Authentication (Recommended)
|
||||
</div>
|
||||
<div className="text-text-neutral-tertiary text-xs">
|
||||
Requires permission to create App Registrations and grant Microsoft
|
||||
Graph admin consent, plus <strong>Owner</strong> on the subscription.{" "}
|
||||
Requires <strong>Global Administrator</strong> or{" "}
|
||||
<strong>Privileged Role Administrator</strong> in Microsoft Entra ID
|
||||
(for the admin consent in step 3), plus <strong>Owner</strong> on the
|
||||
target subscription (step 5).{" "}
|
||||
<Link
|
||||
href={DOCS_CERT_GENERATION_URL}
|
||||
target="_blank"
|
||||
@@ -97,8 +99,8 @@ export const AzureCertificateCredentialsForm = ({
|
||||
<li>
|
||||
<div className="flex flex-col items-start gap-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<span>
|
||||
Register an Azure application, then copy its Directory
|
||||
(tenant) ID and Application (client) ID.
|
||||
Register an Azure application. From its Overview page, copy
|
||||
the Directory (tenant) ID and Application (client) ID.
|
||||
</span>
|
||||
<Button variant="link" size="link-sm" asChild>
|
||||
<a
|
||||
@@ -115,8 +117,8 @@ export const AzureCertificateCredentialsForm = ({
|
||||
<li>
|
||||
<div className="flex flex-col items-start gap-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<span>
|
||||
Generate the certificate. The private bundle is filled below
|
||||
and submitted to Prowler only when you connect.
|
||||
Generate a certificate. The private bundle fills the field
|
||||
below and <code>prowler-cert.cer</code> downloads for step 3.
|
||||
</span>
|
||||
<Button
|
||||
type="button"
|
||||
@@ -159,13 +161,16 @@ export const AzureCertificateCredentialsForm = ({
|
||||
className="flex list-decimal flex-col gap-3 pl-5 text-sm"
|
||||
>
|
||||
<li>
|
||||
Upload <code>prowler-cert.cer</code> under Certificates &
|
||||
secrets. Add Microsoft Graph application permissions:
|
||||
AuditLog.Read.All, Directory.Read.All (or Domain.Read.All), and
|
||||
Policy.Read.All. Then grant admin consent.
|
||||
In your App Registration, upload <code>prowler-cert.cer</code>{" "}
|
||||
under <em>Certificates & secrets</em>. Then in{" "}
|
||||
<em>API permissions</em>, add the Microsoft Graph{" "}
|
||||
<strong>application</strong> permissions{" "}
|
||||
<code>AuditLog.Read.All</code>, <code>Directory.Read.All</code>,
|
||||
and <code>Policy.Read.All</code>, and click{" "}
|
||||
<em>Grant admin consent</em>.
|
||||
</li>
|
||||
<li>
|
||||
Copy the Service Principal Object ID from{" "}
|
||||
Open{" "}
|
||||
<Link
|
||||
href={AZURE_PORTAL_ENTERPRISE_APPLICATIONS_URL}
|
||||
target="_blank"
|
||||
@@ -175,7 +180,8 @@ export const AzureCertificateCredentialsForm = ({
|
||||
<ExternalLink className="size-3.5 shrink-0" />
|
||||
<span>Enterprise applications</span>
|
||||
</Link>
|
||||
.
|
||||
, select the same app, and copy its Object ID (different from the
|
||||
App Registration's Object ID).
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
@@ -191,9 +197,9 @@ export const AzureCertificateCredentialsForm = ({
|
||||
<li>
|
||||
<div className="flex flex-col items-start gap-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<span>
|
||||
Deploy subscription RBAC with the Service Principal Object ID.
|
||||
The template creates ProwlerRole and assigns Reader and
|
||||
ProwlerRole; it does not create Entra resources.
|
||||
Deploy the template with the Service Principal Object ID from
|
||||
step 4. It grants Reader and a custom ProwlerRole on the
|
||||
subscription.
|
||||
</span>
|
||||
<Button variant="default" size="sm" asChild>
|
||||
<a
|
||||
@@ -222,8 +228,8 @@ export const AzureCertificateCredentialsForm = ({
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Return to Prowler and complete the fields below. The generated
|
||||
certificate bundle is already filled.
|
||||
Return to Prowler and paste the Tenant ID and Client ID from step
|
||||
1 into the fields below. The certificate field is already filled.
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
@@ -235,7 +241,7 @@ export const AzureCertificateCredentialsForm = ({
|
||||
type="text"
|
||||
label="Tenant ID"
|
||||
labelPlacement="inside"
|
||||
placeholder="Enter the Tenant ID"
|
||||
placeholder="Directory (tenant) ID"
|
||||
variant="bordered"
|
||||
isRequired
|
||||
/>
|
||||
@@ -245,7 +251,7 @@ export const AzureCertificateCredentialsForm = ({
|
||||
type="text"
|
||||
label="Client ID"
|
||||
labelPlacement="inside"
|
||||
placeholder="Enter the Client ID"
|
||||
placeholder="Application (client) ID"
|
||||
variant="bordered"
|
||||
isRequired
|
||||
/>
|
||||
|
||||
Reference in new issue
Block a user