# Utilisation de l'API S3

Le stockage objet ZSoftly est compatible S3. Tout outil ou SDK prenant en charge S3 fonctionne avec celui-ci.

Points de terminaison :

| Région | Point de terminaison |
| --- | --- |
| YUL (Montreal) | `https://objects.yul.zcp.zsoftly.ca` |
| YOW (Ottawa) | `https://objects.yow.zcp.zsoftly.ca` |

Les exemples ci-dessous utilisent le point de terminaison YUL. Remplacez-le par YOW si votre compartiment se trouve à Ottawa.

### Trouver le nom de votre compartiment

Avant d’écrire une URL de point de terminaison, confirmez le véritable nom du compartiment. La plateforme ajoute un suffixe numérique au nom demandé lors de la création. Un compartiment demandé sous le nom `my-bucket` existe sous un nom du type `my-bucket-001024`. C’est cette valeur suffixée que l’API S3 reconnaît. Utiliser le nom que vous avez saisi renvoie `NoSuchBucket` même si le compartiment existe.

```bash
zcp object-storage bucket list <storage-slug> --region os-yul --project <project-slug>
```

```plaintext
SLUG                NAME                OBJECTS  SIZE (GB)  STATUS
my-bucket-001024    my-bucket-001024    0                   Inactive
```

Utilisez cette valeur partout ci-dessous à la place de `my-bucket`. Un compartiment affichant `Inactive` avec zéro objet est normal tant que rien n’y a été écrit.

Les sous-commandes de compartiment de la CLI sont réparties en deux groupes. Celles qui passent par la passerelle S3 (`object …`, `bucket versioning`, `bucket policy`, `bucket lifecycle`, `bucket cors`, `bucket tag`, `bucket empty`) prennent le nom du compartiment, même si leur aide indique `<bucket-slug>`. Seule `bucket delete`, qui passe par le plan de contrôle, prend le slug. En pratique, le nom et le slug sont généralement la même chaîne suffixée.

### Se connecter et lister les compartiments

Configurez votre client avec le point de terminaison régional et vos clés d’accès, puis listez vos compartiments. Choisissez votre langage :

#### AWS CLI

```bash
# Store your credentials once
aws configure set aws_access_key_id <access-key>
aws configure set aws_secret_access_key <secret-key>


# List buckets
aws s3 ls --endpoint-url https://objects.yul.zcp.zsoftly.ca
```

#### Python

```python
import boto3


s3 = boto3.client(
    "s3",
    endpoint_url="https://objects.yul.zcp.zsoftly.ca",
    aws_access_key_id="<access-key>",
    aws_secret_access_key="<secret-key>",
)


for bucket in s3.list_buckets()["Buckets"]:
    print(bucket["Name"])
```

#### JavaScript

```js
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';


const client = new S3Client({
  endpoint: 'https://objects.yul.zcp.zsoftly.ca',
  region: 'us-east-1',
  credentials: { accessKeyId: '<access-key>', secretAccessKey: '<secret-key>' },
  forcePathStyle: true,
});


const { Buckets } = await client.send(new ListBucketsCommand({}));
for (const b of Buckets ?? []) console.log(b.Name);
```

#### TypeScript

```ts
import { S3Client, ListBucketsCommand, type Bucket } from '@aws-sdk/client-s3';


const client = new S3Client({
  endpoint: 'https://objects.yul.zcp.zsoftly.ca',
  region: 'us-east-1',
  credentials: { accessKeyId: '<access-key>', secretAccessKey: '<secret-key>' },
  forcePathStyle: true,
});


const { Buckets } = await client.send(new ListBucketsCommand({}));
Buckets?.forEach((b: Bucket) => console.log(b.Name));
```

#### Go

```go
package main


import (
  "context"
  "fmt"


  "github.com/aws/aws-sdk-go-v2/aws"
  "github.com/aws/aws-sdk-go-v2/credentials"
  "github.com/aws/aws-sdk-go-v2/service/s3"
)


func main() {
  client := s3.New(s3.Options{
    BaseEndpoint: aws.String("https://objects.yul.zcp.zsoftly.ca"),
    Region:       "us-east-1",
    Credentials:  credentials.NewStaticCredentialsProvider("<access-key>", "<secret-key>", ""),
    UsePathStyle: true,
  })


  out, err := client.ListBuckets(context.TODO(), &s3.ListBucketsInput{})
  if err != nil {
    panic(err)
  }
  for _, b := range out.Buckets {
    fmt.Println(*b.Name)
  }
}
```

#### C#

```csharp
using Amazon.S3;


var config = new AmazonS3Config
{
    ServiceURL = "https://objects.yul.zcp.zsoftly.ca",
    ForcePathStyle = true,
};
using var client = new AmazonS3Client("<access-key>", "<secret-key>", config);


var response = await client.ListBucketsAsync();
foreach (var bucket in response.Buckets)
{
    Console.WriteLine(bucket.BucketName);
}
```

#### Java

```java
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration;


import java.net.URI;


public class ListBuckets {
    public static void main(String[] args) {
        S3Client s3 = S3Client.builder()
            .endpointOverride(URI.create("https://objects.yul.zcp.zsoftly.ca"))
            .region(Region.US_EAST_1)
            .credentialsProvider(StaticCredentialsProvider.create(
                AwsBasicCredentials.create("<access-key>", "<secret-key>")))
            .serviceConfiguration(S3Configuration.builder()
                .pathStyleAccessEnabled(true).build())
            .build();


        s3.listBuckets().buckets().forEach(b -> System.out.println(b.name()));
    }
}
```

#### Ruby

```ruby
require "aws-sdk-s3"


s3 = Aws::S3::Client.new(
  endpoint: "https://objects.yul.zcp.zsoftly.ca",
  region: "us-east-1",
  access_key_id: "<access-key>",
  secret_access_key: "<secret-key>",
  force_path_style: true
)


s3.list_buckets.buckets.each { |b| puts b.name }
```

#### PHP

```php
<?php
require "vendor/autoload.php";


use Aws\S3\S3Client;


$s3 = new S3Client([
    "version" => "latest",
    "region" => "us-east-1",
    "endpoint" => "https://objects.yul.zcp.zsoftly.ca",
    "use_path_style_endpoint" => true,
    "credentials" => [
        "key" => "<access-key>",
        "secret" => "<secret-key>",
    ],
]);


foreach ($s3->listBuckets()["Buckets"] as $bucket) {
    echo $bucket["Name"] . "\n";
}
```

Activez toujours l’adressage path-style : `forcePathStyle` (JS/TS), `UsePathStyle` (Go), `ForcePathStyle` (C#), `pathStyleAccessEnabled` (Java), `force_path_style` (Ruby) ou `use_path_style_endpoint` (PHP). Le stockage objet ZSoftly l’exige. Le style virtual-hosted n’est pas pris en charge.

N’activez pas le chiffrement par défaut des compartiments (SSE-S3). La passerelle de stockage ne dispose pas encore de backend de clés de chiffrement, et un compartiment configuré avec le chiffrement par défaut rejette tous les téléversements suivants avec `InvalidArgument` jusqu’au retrait du paramètre. Cela vaut pour `PutBucketEncryption` depuis n’importe quel SDK ainsi que pour `aws s3api put-bucket-encryption`.

Retirez le paramètre sur un compartiment déjà touché :

```bash
zcp object-storage bucket encryption status <storage-slug> <bucket-name>
zcp object-storage bucket encryption disable <storage-slug> <bucket-name>
```

Pour chiffrer ce que vous stockez aujourd’hui, chiffrez côté client avant le téléversement. Voir [Sauvegarder Vaultwarden vers le stockage objet avec restic](https://docs.zcp.zsoftly.ca/fr/tutorials/backup-vaultwarden-restic-object-storage/) pour un exemple complet.

### Opérations courantes

Une fois votre client (ou AWS CLI) configuré, toutes les opérations S3 standard fonctionnent. Avec AWS CLI :

```bash
# Create a bucket
aws s3 mb s3://my-bucket --endpoint-url https://objects.yul.zcp.zsoftly.ca


# Upload a file
aws s3 cp ./file.txt s3://my-bucket/ --endpoint-url https://objects.yul.zcp.zsoftly.ca


# Download a file
aws s3 cp s3://my-bucket/file.txt ./file.txt --endpoint-url https://objects.yul.zcp.zsoftly.ca


# List objects in a bucket
aws s3 ls s3://my-bucket/ --endpoint-url https://objects.yul.zcp.zsoftly.ca


# Delete an object
aws s3 rm s3://my-bucket/file.txt --endpoint-url https://objects.yul.zcp.zsoftly.ca
```

### s3cmd

[s3cmd](https://s3tools.org/s3cmd) est un client en ligne de commande autonome pour le stockage compatible S3. Installez-le, puis créez `~/.s3cfg` :

```ini
[default]
access_key = <access-key>
secret_key = <secret-key>
host_base = objects.yul.zcp.zsoftly.ca
host_bucket = objects.yul.zcp.zsoftly.ca
use_https = True
```

Ce fichier contient votre clé secrète. Limitez donc ses autorisations :

```bash
chmod 600 ~/.s3cfg
```

Définir `host_bucket` sur la même valeur que `host_base`, sans espace réservé pour le compartiment, force l’adressage path-style requis par le service. Pour un compartiment à Ottawa, utilisez `objects.yow.zcp.zsoftly.ca`.

Exécutez les commandes courantes :

```bash
s3cmd ls                                    # list your buckets
s3cmd mb s3://my-bucket                      # create a bucket
s3cmd put ./file.txt s3://my-bucket/         # upload a file
s3cmd get s3://my-bucket/file.txt .          # download a file
s3cmd sync ./local-dir/ s3://my-bucket/dir/  # sync a folder
s3cmd rm s3://my-bucket/file.txt             # delete an object
```

Voir aussi : [Clés d’accès](https://docs.zcp.zsoftly.ca/fr/public-cloud/storage/object-storage/access-keys), [Créer un compartiment](https://docs.zcp.zsoftly.ca/fr/public-cloud/storage/object-storage/create-bucket)
