Existe t'il une fonction pour récupérer une url, utilisable par n'importe qui, pour télécharger un fichier depuis un conteneur azure ?


Pour ajouter un fichier dans un nouveau blob d'un conteneur azure, je n'ai pas de pb.
Ca fonctionne bien :
- TAzureConnectionInfo pour se connecter.
- TAzureBlobService pour naviguer dans les conteneurs, et PutBlockBlob() pour envoyer le fichier.

Énumérer les blobs d'un conteneur avec ListBlobs(), permet d'accéder à quelques informations des blobs, dont TAzureBlob.Url.
Mais cette url n'est valable que si le conteneur n'est pas privé (le paramètre "niveau d'accès anonyme" du conteneur différent de "private"), ce qui n'est pas sécurisé.

Toutes les recherches que j'ai faites indiquent la même chose : il faut construire soit-même une url avec un certains nombre de paramètres, dont une signature constituée de la permission + #10 + une date.

https://<nom_du_compte>.blob.core.windows.net/<nom_du_container>/<nom_du_fichier>?sv=<version_service>&ss=<service>&srt=<type_de_ressource>&sp=<permissions>&se=<expiration>&st=<heure_de_début>&spr=<protocoles>&sig=<signature>
J'ai beau essayer aléatoirement d'ajouter des paramètres, ou de bricoler cette signature, j'obtiens diverses erreurs.
La dernière en date : "Make sure the value of Authorization header is formed correctly including the signature".

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function TFrm_AzureConnect.GenerateBlobSAS(const accountName, accountKey, containerName, blobName: String; const permissions: String; const expiry: TDateTime): String;
var
  http: TIdHTTP;
  url, signature: String;
  hmac: TIdHMACSHA1;   // TIdHMACSHA256
  signatureBytes: TIdBytes;   // TBytes;
begin
  http := TIdHTTP.Create(nil);
  try
    http.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(http);
    http.Request.CustomHeaders.Add('x-ms-version:2019-12-12');
 
    url := Format('https://%s.blob.core.windows.net/%s/%s', [accountName, containerName, blobName]);
    signature := Format('%s'#10'%s', [permissions, FormatDateTime('yyyy-mm-dd', expiry)]);
 
    hmac := TIdHMACSHA1.Create;
    try
        hmac.Key := ConvertirTableauTIdBytes(TEncoding.ASCII.GetBytes(accountKey));
        signatureBytes := hmac.HashValue(ConvertirAnsiStringTIdBytes(AnsiString(signature)));
        signature := TNetEncoding.Base64.EncodeBytesToString(signatureBytes);
    finally
      hmac.Free;
    end;
    url := url + '?ss=b&srt=sco&sr=c&spr=https&st=' + FormatDateTime('yyyy-mm-dd', Now) + 'T' + FormatDateTime('hh:nn:ss', Now) + 'Z&se=' + FormatDateTime('yyyy-mm-dd', expiry) + 'T' + FormatDateTime('hh:nn:ss', expiry) + 'Z&sp=' + permissions + '&sig=' + signature;
 
    try
      Result := http.Get(url);
    except
      on E: Exception do
      begin
        RichEdit.Lines.Add('      # ' + E.Message);
        Exit;
      end;
    end;
  finally
    http.Free;
  end;
end;
Ce qui me surprend, c'est qu'il n'y ait pas une simple fonction à appeler pour faire ça.