Une inscription d’application dans Entra se fait :
Install-Module Microsoft.Graph Import-Module Microsoft.Graph
La permission Sites.Selected restreint l'accès au site explicitement autorisé via Graph.
Une autorisation d'application ne nécessite pas de compte utilisateur :
Connect-MgGraph -Scopes "Application.ReadWrite.All","AppRoleAssignment.ReadWrite.All" Welcome to Microsoft Graph! Connected via delegated access using 14d82eec-204b-4c2f-b7e8-296a70dab67e Readme: https://aka.ms/graph/sdk/powershell SDK Docs: https://aka.ms/graph/sdk/powershell/docs API Docs: https://aka.ms/graph/docs NOTE: You can use the -NoWelcome parameter to suppress this message.
$app = New-MgApplication -DisplayName "Application"
$sp = New-MgServicePrincipal -AppId $app.AppId
Cela ne peut pas se faire depuis l'interface d'administration Entra ID mais en utilisant Powershell.
$cert = New-SelfSignedCertificate ` -Subject "CN=applicaton" ` -CertStoreLocation "Cert:\CurrentUSer\My" ` -KeySpec Signature ` -KeyUsage DigitalSignature ` -KeyExportPolicy Exportable ` -HashAlgorithm SHA256 ` -KeyLength 2048 ` -NotAfter (Get-Date).AddYears(4) $cert.Thumbprint
$cert.Thumbprint
Get-Item "Cert:\CurrentUSer\My\<TON_THUMBPRINT>"
$cert = Get-Item "Cert:\CurrentUSer\My\<THUMBPRINT>" $cert.HasPrivateKey
$cert.HasPrivateKey doit renvoyer True
* Export du certificat PUBLIC à importer dans Entra ID
Export-Certificate `
-Cert "Cert:\CurrentUSer\My\$($cert.Thumbprint)" `
-FilePath "application.cer"
Connect-MgGraph ` -TenantId "<TENANT_ID>" ` -ClientId "<APP_ID>" ` -CertificateThumbprint "<THUMBPRINT>" => Résultat attendu Plain TextWelcome To Microsoft Graph!
Get-MgContext
=> on doit voir :
ClientId : <id client>
TenantId : <ID tenant>
Scopes : {Sites.Selected}
AuthType : AppOnly
TokenCredentialType : ClientCertificate
CertificateThumbprint : <empreinte>
# deconnexion
Disconnect-MgGraph
# Connexion admin
Connect-MgGraph -Scopes "Sites.FullControl.All"
# Récupérer le site
$site = Get-MgSite -SiteId "mondomaine.sharepoint.com:/sites/MonSite"
# Donner accès controle total à l'application (fullcontrol / read / write)
New-MgSitePermission `
-SiteId $site.Id `
-Roles "fullcontrol" `
-GrantedToIdentities @{
Application = @{
Id = "ID application"
DisplayName = "application"
}
}
Connect-MgGraph `
-TenantId "1ae69c2d-61b2-4de4-84c7-2a4dd0de7330" `
-ClientId "5c82fc87-6e0c-413f-ac12-6d784af9a249" `
-CertificateThumbprint "97F825CFD5C0371D28E1D691140A084B9C2C4386"
Get-MgSite -SiteId "mondomaine.sharepoint.com:/sites/MonSite"
$site = Get-MgSite -SiteId "mondomaine.sharepoint.com:/sites/MonSite" $site.Id => Afficher le GUID du site du type : xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
$drive = Get-MgSiteDrive -SiteId $site.Id $drive.Id => Affiche un DriveId Type : documentLibrary
New-MgDriveRootChild `
-DriveId $drive.Id `
-AdditionalProperties @{
"name" = "Test-Dossier"
"folder" = @{}
"@microsoft.graph.conflictBehavior" = "rename"
}
=> Résultat attendu
Id : 01ABCDEF....
Name : Test-Dossier
=> Dossier créé avec succès à vérifier dans SharePoint
$items = Get-MgDriveRootChild -DriveId $drive.Id
$parent = $items | Where-Object { $_.Name -eq "General" }
$parent.Id
New-MgDriveItemChild `
-DriveId $drive.Id `
-DriveItemId $parent.Id `
-AdditionalProperties @{
"name" = "Test-SousDossier"
"folder" = @{}
"@microsoft.graph.conflictBehavior" = "rename"
}
PnP.PowerShell supporte :
Install-Module PnP.PowerShell -Scope CurrentUser
$cert = New-SelfSignedCertificate `
-Subject "CN=MinioS3Sync" `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-CertStoreLocation "Cert:\CurrentUser\My" `
-NotAfter (Get-Date).AddYears(3)
Export-Certificate `
-Cert $cert `
-FilePath "./minio-s3.cer"
$password = Read-Host "Mot de passe du certificat" -AsSecureString
Export-PfxCertificate `
-Cert $cert `
-FilePath "./minio-s3.pfx" `
-Password $password
``
Connect-PnPOnline ` -Url "https://educvaladonlimogesfr-admin.sharepoint.com" ` -ClientId "ad39ff78-4116-43d6-86cf-3dfa8f120aa3" ` -Tenant "educvaladonlimogesfr.onmicrosoft.com" ` -CertificatePath "./minio-s3.pfx" ` -CertificatePassword $password
Grant-PnPAzureADAppSitePermission ` -AppId "ad39ff78-4116-43d6-86cf-3dfa8f120aa3" ` -DisplayName "Minio-S3c" ` -Site "https://educvaladonlimogesfr.sharepoint.com/sites/Signaturenumrique" ` -Permissions Write
Connect-PnPOnline -Url "https://<tenant>-admin.sharepoint.com" -ClientId "<appID>" -ClientSecret "<secret>"
Le script :
apt install jq
#!/usr/bin/env bash
### ---------------------------------------------------------------------------
### CONFIGURATION À RENSEIGNER
### ---------------------------------------------------------------------------
TENANT_ID="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
CLIENT_ID="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
CLIENT_SECRET="YOUR_APP_SECRET"
HOSTNAME="contoso.sharepoint.com" # domaine SharePoint
SITE_PATH="DocumensoSite" # nom du site SharePoint
DRIVE_NAME="Documents" # nom de la bibliothèque (ex: "Documents")
RCLONE_REMOTE="sharepoint" # nom du remote rclone
RCLONE_MINIO="s3minio:documenso" # bucket minio
RCLONE_SHAREPOINT="${RCLONE_REMOTE}:${DRIVE_NAME}"
### ---------------------------------------------------------------------------
echo "1. Obtention du token OAuth2..."
ACCESS_TOKEN=$(
curl -s -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=$CLIENT_ID" \
-d "scope=https://graph.microsoft.com/.default" \
-d "client_secret=$CLIENT_SECRET" \
-d "grant_type=client_credentials" \
"https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \
| jq -r .access_token
)
if [[ "$ACCESS_TOKEN" == "null" || -z "$ACCESS_TOKEN" ]]; then
echo "❌ Impossible de générer un token ! Vérifie ton CLIENT_ID / SECRET."
exit 1
fi
echo " Token obtenu."
### ---------------------------------------------------------------------------
echo "2. Récupération automatique du site-id..."
SITE_INFO=$(curl -s -X GET \
-H "Authorization: Bearer $ACCESS_TOKEN" \
"https://graph.microsoft.com/v1.0/sites/$HOSTNAME:/sites/$SITE_PATH?$select=id,webUrl")
SITE_ID=$(echo "$SITE_INFO" | jq -r '.id')
if [[ "$SITE_ID" == "null" || -z "$SITE_ID" ]]; then
echo "❌ Impossible de récupérer le site-id !"
echo "Réponse brute:"
echo "$SITE_INFO"
exit 1
fi
echo " SITE_ID trouvé : $SITE_ID"
### ---------------------------------------------------------------------------
echo "3. Récupération automatique du drive-id de la bibliothèque $DRIVE_NAME..."
DRIVES_LIST=$(curl -s -X GET \
-H "Authorization: Bearer $ACCESS_TOKEN" \
"https://graph.microsoft.com/v1.0/sites/$SITE_ID/drives")
DRIVE_ID=$(echo "$DRIVES_LIST" | jq -r ".value[] | select(.name==\"$DRIVE_NAME\") | .id")
if [[ -z "$DRIVE_ID" ]]; then
echo "❌ Impossible de trouver la bibliothèque '$DRIVE_NAME'"
echo "Réponse brute:"
echo "$DRIVES_LIST"
exit 1
fi
echo "DRIVE_ID trouvé : $DRIVE_ID"
### ---------------------------------------------------------------------------
echo "4. Attribution de la permission Sites.Selected (write) à l'application..."
ASSIGN_RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"roles\": [\"write\"],
\"grantedToIdentities\": [
{
\"application\": {
\"id\": \"$CLIENT_ID\"
}
}
]
}" \
"https://graph.microsoft.com/v1.0/sites/$SITE_ID/permissions")
echo " Permission appliquée."
echo "Réponse API :"
echo "$ASSIGN_RESPONSE"
### ---------------------------------------------------------------------------
echo "5. Test d'accès SharePoint avec rclone..."
docker exec -it rclone-sync rclone lsd "$RCLONE_SHAREPOINT"
echo " Configuration terminée avec succès !"
echo "SITE_ID = $SITE_ID"
echo "DRIVE_ID = $DRIVE_ID"
bash setup_sharepoint_access.sh