Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions cloud-accounts/connecting-a-cloud-account.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,8 @@ Before Porter can create a cluster, you need to grant it access to your cloud ac
- `Microsoft.Blueprint/blueprintAssignments/delete`
- `Microsoft.Compute/galleries/share/action`
- Creates the `azure-porter-federated-sp` app registration and matching service principal, then assigns the custom role at the subscription scope
- Adds these Microsoft Graph application permissions:
- Application.ReadWrite.All
- Directory.ReadWrite.All
- Domain.Read.All
- Group.Create
- Group.ReadWrite.All
- RoleManagement.ReadWrite.Directory
- User.ReadWrite.All
- Grants admin consent for the Graph permissions
- Makes the service principal an owner of its own app registration
- Adds the `Application.ReadWrite.OwnedBy` Microsoft Graph application permission and grants admin consent for it. This is the only Graph permission Porter uses, and Porter uses it solely to manage the federated identity credentials on the app registration the service principal owns. Its write access is limited to applications the service principal creates or owns, so Porter cannot modify any other application in your tenant
- Adds a federated identity credential on the app registration trusting Porter's OIDC issuer (audience `api://AzureADTokenExchange`)
- Waits for Azure's [eventually consistent IAM service](https://devblogs.microsoft.com/identity/designing-for-eventual-consistency-for-microsoft-entra/) to propogate changes.
- Outputs the app registration's metadata: **Subscription ID**, **Application (Client) ID**, and **Tenant ID**
Expand Down
34 changes: 26 additions & 8 deletions scripts/setup-azure-porter-wif.sh
Original file line number Diff line number Diff line change
Expand Up @@ -334,22 +334,39 @@ assign_custom_role() {
print_success "Role assignment ensured"
}

# Make the service principal an owner of its own app registration. Application.ReadWrite.OwnedBy
# only reaches registrations the caller owns, so without this Porter cannot manage the federated
# identity credentials on the registration. Kept separate from create_app_registration so it is
# reconciled on every run, like assign_custom_role.
ensure_app_owner() {
print_status "Ensuring the service principal owns its app registration..."

SP_OBJECT_ID=$(az ad sp show --id "$APP_ID" --query id -o tsv)
if [ -z "$SP_OBJECT_ID" ]; then
print_fatal "Failed to look up the service principal for app registration $APP_ID"
fi

if az ad app owner list --id "$APP_ID" --query "[].id" -o tsv 2>/dev/null | grep -qx "$SP_OBJECT_ID"; then
print_success "Service principal is already an owner of the app registration"
return
fi

az ad app owner add --id "$APP_ID" --owner-object-id "$SP_OBJECT_ID"
print_success "Service principal added as an owner of the app registration"
}

# Function to add API permissions
add_api_permissions() {
print_status "Adding Microsoft Graph API permissions..."

# Microsoft Graph App ID (constant)
MSGRAPH_APP_ID="00000003-0000-0000-c000-000000000000"

# Required permission names
# Porter's only Microsoft Graph operation is managing federated identity credentials on this
# app registration. Application.ReadWrite.OwnedBy covers that and is scoped to registrations
# the service principal owns (see ensure_app_owner) rather than every application in the tenant.
required_permissions=(
"Application.ReadWrite.All"
"Directory.ReadWrite.All"
"Domain.Read.All"
"Group.Create"
"Group.ReadWrite.All"
"RoleManagement.ReadWrite.Directory"
"User.ReadWrite.All"
"Application.ReadWrite.OwnedBy"
)

# Get Microsoft Graph service principal to fetch permission IDs dynamically
Expand Down Expand Up @@ -668,6 +685,7 @@ main() {
create_custom_role
create_app_registration
assign_custom_role
ensure_app_owner
add_api_permissions

# Try to grant admin consent, but don't fail if it doesn't work
Expand Down