העברה פשוטה מ-Amazon S3 ל-Cloud Storage

המאמר הזה מתאר איך לבצע העברה פשוטה מ-Amazon Simple Storage Service (Amazon S3) ל-Cloud Storage. בהעברה פשוטה, משתמשים בכלים ובספריות הקיימים ליצירת בקשות REST מאומתות ל-Amazon S3, כדי לשלוח בקשות מאומתות ל-Cloud Storage.

העברה מ-Amazon S3 ל-Cloud Storage בתרחיש העברה פשוט

כדי לשלוח בקשות ל-Cloud Storage, צריך לבצע את השלבים הבאים:

  • משתמשים בכותרת x-amz-project-id כששולחים בקשות ליצירה ולרישום של קטגוריות.
  • קבלת מפתח אימות באמצעות HMAC (קוד אימות הודעות המבוסס על גיבוב).
  • בכלים או בספריות הקיימים שלכם, מבצעים את השינויים הבאים:

    • שינוי נקודת הקצה (endpoint) של הבקשה כדי שתשתמש בנקודת הקצה של בקשת XML API של Cloud Storage.
    • החלפת הגישה והמפתח הסודי של Amazon Web Services (AWS) במזהה גישה והסוד המתאימים של Cloud Storage (שנקראים יחד מפתח HMAC של Cloud Storage שלכם).
    • מוודאים שהכותרות של x-amz- משתמשות בערכים נתמכים של Cloud Storage. לדוגמה, x-amz-storage-class צריך להשתמש באחד מסוגי האחסון (storage class) הזמינים של Cloud Storage.

      כשמשתמשים ב-Cloud Storage XML API בתרחיש העברה פשוט, ציון מזהה החתימה AWS בכותרת Authorization מאפשר ל-Cloud Storage לדעת שצריך לצפות לכותרות x-amz-* ולתחביר XML של Amazon S3 ACL בבקשה. ‫Cloud Storage מבצע עיבוד כותרות x-amz-* בעלות שוות ערך ל-x-goog-*, כמו אלה שמופיעות בטבלת הכותרות, והוא מבצע עיבוד של הכותרת x-amz-decoded-content-length.

  • אחרי ביצוע השינויים האלו, אפשר להתחיל את השימוש בכלים ובספריות הקיימים כדי לשלוח בקשות HMAC ל-Cloud Storage.

    הדוגמאות הבאות מציגות איך ליצור רשימה של קטגוריות של Cloud Storage באמצעות ה-SDK של Amazon S3:

    Go

    מידע נוסף מופיע בחומרי העזר של Cloud Storage Go API.

    כדי לבצע אימות ב-Cloud Storage, אתם צריכים להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.

    לפני שמריצים דוגמאות קוד, צריך להגדיר את משתנה הסביבה GOOGLE_CLOUD_UNIVERSE_DOMAIN לערך s3nsapis.fr.

    import (
    	"context"
    	"fmt"
    	"io"
    	"time"
    
    	"github.com/aws/aws-sdk-go/aws"
    	"github.com/aws/aws-sdk-go/aws/credentials"
    	"github.com/aws/aws-sdk-go/aws/session"
    	"github.com/aws/aws-sdk-go/service/s3"
    )
    
    func listGCSBuckets(w io.Writer, googleAccessKeyID string, googleAccessKeySecret string) error {
    	// googleAccessKeyID := "Your Google Access Key ID"
    	// googleAccessKeySecret := "Your Google Access Key Secret"
    
    	// Create a new client and do the following:
    	// 1. Change the endpoint URL to use the Google Cloud Storage XML API endpoint.
    	// 2. Use Cloud Storage HMAC Credentials.
    	sess := session.Must(session.NewSession(&aws.Config{
    		Region:      aws.String("auto"),
    		Endpoint:    aws.String("https://storage.googleapis.com"),
    		Credentials: credentials.NewStaticCredentials(googleAccessKeyID, googleAccessKeySecret, ""),
    	}))
    
    	client := s3.New(sess)
    	ctx := context.Background()
    
    	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
    	defer cancel()
    	result, err := client.ListBucketsWithContext(ctx, &s3.ListBucketsInput{})
    	if err != nil {
    		return fmt.Errorf("ListBucketsWithContext: %w", err)
    	}
    
    	fmt.Fprintf(w, "Buckets:")
    	for _, b := range result.Buckets {
    		fmt.Fprintf(w, "%s\n", aws.StringValue(b.Name))
    	}
    
    	return nil
    }
    

    Java

    למידע נוסף, קראו את מאמרי העזרה של Cloud Storage Java API.

    כדי לבצע אימות ב-Cloud Storage, אתם צריכים להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.

    לפני שמריצים דוגמאות קוד, צריך להגדיר את משתנה הסביבה GOOGLE_CLOUD_UNIVERSE_DOMAIN לערך s3nsapis.fr.

    import com.amazonaws.auth.AWSStaticCredentialsProvider;
    import com.amazonaws.auth.BasicAWSCredentials;
    import com.amazonaws.client.builder.AwsClientBuilder;
    import com.amazonaws.services.s3.AmazonS3;
    import com.amazonaws.services.s3.AmazonS3ClientBuilder;
    import com.amazonaws.services.s3.model.Bucket;
    import java.util.List;
    
    public class ListGcsBuckets {
      public static void listGcsBuckets(String googleAccessKeyId, String googleAccessKeySecret) {
    
        // String googleAccessKeyId = "your-google-access-key-id";
        // String googleAccessKeySecret = "your-google-access-key-secret";
    
        // Create a BasicAWSCredentials using Cloud Storage HMAC credentials.
        BasicAWSCredentials googleCreds =
            new BasicAWSCredentials(googleAccessKeyId, googleAccessKeySecret);
    
        // Create a new client and do the following:
        // 1. Change the endpoint URL to use the Google Cloud Storage XML API endpoint.
        // 2. Use Cloud Storage HMAC Credentials.
        AmazonS3 interopClient =
            AmazonS3ClientBuilder.standard()
                .withEndpointConfiguration(
                    new AwsClientBuilder.EndpointConfiguration(
                        "https://storage.googleapis.com", "auto"))
                .withCredentials(new AWSStaticCredentialsProvider(googleCreds))
                .build();
    
        // Call GCS to list current buckets
        List<Bucket> buckets = interopClient.listBuckets();
    
        // Print bucket names
        System.out.println("Buckets:");
        for (Bucket bucket : buckets) {
          System.out.println(bucket.getName());
        }
    
        // Explicitly clean up client resources.
        interopClient.shutdown();
      }

    Python

    למידע נוסף, קראו את מאמרי העזרה של Cloud Storage Python API.

    כדי לבצע אימות ב-Cloud Storage, אתם צריכים להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.

    לפני שמריצים דוגמאות קוד, צריך להגדיר את משתנה הסביבה GOOGLE_CLOUD_UNIVERSE_DOMAIN לערך s3nsapis.fr.

    import boto3  # type: ignore
    
    
    def list_gcs_buckets(
        google_access_key_id: str, google_access_key_secret: str
    ) -> List[str]:
        """Lists all Cloud Storage buckets using AWS SDK for Python (boto3)
        Positional arguments:
            google_access_key_id: hash-based message authentication code (HMAC) access ID
            google_access_key_secret: HMAC access secret
    
        Returned value is a list of strings, one for each bucket name.
    
        To use this sample:
        1. Create a Cloud Storage HMAC key: https://cloud.google.com/storage/docs/authentication/managing-hmackeys#create
        2. Change endpoint_url to a Google Cloud Storage XML API endpoint.
    
        To learn more about HMAC: https://cloud.google.com/storage/docs/authentication/hmackeys#overview
        """
        client = boto3.client(
            "s3",
            region_name="auto",
            endpoint_url="https://storage.googleapis.com",
            aws_access_key_id=google_access_key_id,
            aws_secret_access_key=google_access_key_secret,
        )
    
        # Call GCS to list current buckets
        response = client.list_buckets()
    
        # Return list of bucket names
        results = []
        for bucket in response["Buckets"]:
            results.append(bucket["Name"])
            print(bucket["Name"])  # Can remove if not needed after development
        return results
    
    

    ציון כותרת של פרויקט

    בבקשות שבהן צריך לציין פרויקט, משתמשים בכותרת x-amz-project-id.

    שימו לב שב-Amazon S3 אין פרויקטים, כך שבהתאם לכלים או לספריות הלקוח שבהם משתמשים, לא בטוח שאפשר לציין כותרת x-amz-project-id.

    שימוש במפתחות HMAC

    כדי להשתמש ב-Cloud Storage XML API בתרחיש העברה פשוט, צריך להשתמש במפתחות של קוד אימות הודעות (HMAC) מבוססי גיבוב של Cloud Storage לפרטי הכניסה. בדרך כלל, צריך ליצור מפתח HMAC המשויך לחשבון שירות. אבל אפשר גם להשתמש במפתח המשויך לחשבון משתמש.

    אימות בתרחיש העברה פשוט

    שימוש בכותרת Authorization

    בשביל פעולות בתרחיש העברה פשוט המחייבות אימות, צריך לכלול כותרת בקשה של Authorization, בדיוק כמו לבקשות אל Amazon S3. תחביר הכותרת Authorization לבקשת Amazon S3 הוא:

    Authorization: AWS4-HMAC-SHA256 Credential=AWS-ACCESS-KEY/CREDENTIAL_SCOPE, SignedHeaders=SIGNED_HEADERS, Signature=SIGNATURE
    

    בתרחיש העברה פשוט, משנים את הכותרת כדי שתשתמש במזהה הגישה של Cloud Storage HMAC, ומוודאים שה-Signature שמצרפים מחושב באמצעות המפתח הסודי של Cloud Storage HMAC:

    Authorization: ALGORITHM Credential=GOOG-ACCESS-ID/CREDENTIAL_SCOPE, SignedHeaders=SIGNED_HEADERS, Signature=SIGNATURE
    

    החלקים של הכותרת של Authorization הם:

    • ALGORITHM: אלגוריתם וגרסת החתימה שבה משתמשים. שימוש ב-AWS4-HMAC-SHA256, מציין שמשתמשים בחתימת HMAC V4 ומתכוונים לשלוח כותרות x-amz-*. אפשר גם להשתמש ב-GOOG4-HMAC-SHA256, שמציין שמשתמשים בחתימת HMAC V4 ומתכוונים לשלוח כותרות x-goog-*, או ב-GOOG4-RSA-SHA256, שמציין שמשתמשים בחתימת RSA V4 ומתכוונים לשלוח כותרות x-goog-*.

    • GOOG-ACCESS-ID: מזהה הגישה משמש לזיהוי הישות שמייצרת את הבקשה וחותמת עליה. בהעברה פשוטה, צריך להחליף את מזהה מפתח הגישה של Amazon Web Service (AWS) שבו משתמשים כדי לגשת ל-Amazon S3 באמצעות מזהה הגישה של Cloud Storage HMAC. מזהה הגישה של Cloud Storage HMAC מתחיל ב-GOOG.

    • CREDENTIAL_SCOPE: ההיקף של פרטי הכניסה, כפי שמוגדר בחתימה. בהעברה פשוטה אין צורך לשנות את ההיקף של פרטי הכניסה אם משתמשים ב-AWS4-HMAC-SHA256 כערך ALGORITHM.

    • SIGNED_HEADERS: רשימת שמות של כותרות שמופרדים באמצעות נקודה-פסיק שנחוצים כדי לחתום על הבקשה הזו. כל הכותרות צריכות להיות באותיות קטנות וממוינות לפי קודי תווים.

      דוגמה למחרוזת כותרת חתומה בסגנון Amazon S3 נראית כך:

      content-type;host;x-amz-date

      בהעברה פשוטה לא צריך לבצע שינויים במחרוזת הכותרת החתומה.

    • SIGNATURE: החתימה שמאפשרת אימות של הבקשה. בהעברה פשוטה, צריך להחליף את פרטי מפתח הגישה של AWS בפרטים המקבילים של מפתח HMAC של Cloud Storage.

    בקשת אימות לדוגמה

    בדוגמאות הבאות מועלה אובייקט בשם /europe/france/paris.jpg לקטגוריה בשם my-travel-maps, מחילים את ה-ACL המוגדר מראש public-read ומגדירים כותרת מטא-נתונים מותאמת אישית לבודקים. זוהי הבקשה לקטגוריה ב-Amazon S3:

    PUT europe/france/paris.jpg HTTP/1.1
    Host: my-travel-maps.s3.amazonaws.com
    Date: Mon, 11 Mar 2019 23:46:19 GMT
    Content-Length: 888814
    Content-Type: image/jpg
    x-amz-acl: public-read
    x-amz-date:20190311T192918Z
    x-amz-meta-reviewer: joe,jane
    Authorization: AWS4-HMAC-SHA256 Credential=AWS-ACCESS-KEY/20190311/us-east-1/s3/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-acl;x-amz-date;x-amz-meta-reviewer, Signature=SIGNATURE
    

    זוהי הבקשה לקטגוריה ב-Cloud Storage:

    PUT europe/france/paris.jpg HTTP/1.1
    Host: my-travel-maps.storage.s3nsapis.fr
    Date: Mon, 11 Mar 2019 23:46:19 GMT
    Content-Length: 888814
    Content-Type: image/jpg
    x-amz-acl: public-read
    x-amz-date:20190311T192918Z
    x-amz-meta-reviewer: joe,jane
    Authorization: AWS4-HMAC-SHA256 Credential=GOOG-ACCESS-ID/20190311/us-east-1/s3/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-acl;x-amz-date;x-amz-meta-reviewer, Signature=SIGNATURE
    

    זוהי הבקשה הקנונית המתאימה שנוצרה עבור הבקשה הזו:

    PUT
    /europe/france/paris.jpg
    
    content-length:888814
    content-type:image/jpg
    host:my-travel-maps.storage.s3nsapis.fr
    x-amz-acl:public-read
    x-amz-date:20190311T192918Z
    x-amz-meta-reviewer:joe,jane
    
    content-length,content-type,host,x-amz-acl,x-amz-date,x-amz-meta-reviewer
    82e3da8b3f35989512e8d428add7eca73ab0e5f36586e66fbad8e1051343cbd2
    

    זוהי המחרוזת המתאימה לחתימה שנוצרה עבור הבקשה הזו:

    AWS4-HMAC-SHA256
    20190311T192918Z
    20190311/us-east-1/s3/aws4_request
    73918a5ff373d7a03e406fbf9ea35675396b06fca2af76c27a5c451fa783ef65
    

    הבקשה הזו לא הכילה כותרת Content-MD5, ולכן מופיעה מחרוזת ריקה בשורה השנייה של ההודעה.

    בקרת גישה בתרחיש העברה פשוטה

    כדי לתמוך בהעברות פשוטות, Cloud Storage מקבל רשימות ACL שנוצרו על ידי Amazon S3. בתרחיש העברה פשוט, משתמשים ב-AWS כמזהה החתימה, וכך מורים ל-Cloud Storage לצפות לתחביר ACL שמשתמש בתחביר ACL ל-XML של Amazon S3. צריך לוודא שלרשימות ה-ACL של Amazon S3 שבהן משתמשים יש מיפוי למודל ACL של Cloud Storage. לדוגמה, אם הכלים והספריות משתמשים בתחביר ACL של Amazon S3 כדי להעניק הרשאת WRITE לקטגוריה, הם צריכים גם להעניק את ההרשאה READ לקטגוריה, כי הרשאות ל-Cloud Storage הן קונצנטריות. כשמעניקים הרשאה ל-WRITE באמצעות התחביר של Cloud Storage, לא צריך לציין גם את ההרשאה WRITE וגם את ההרשאה READ.

    Cloud Storage תומך בתחביר של רשימות ACL של Amazon S3 בתרחישים הבאים:

    • בעקבות בקשה ל-Cloud Storage לאחזר רשימות ACL (לדוגמה, אובייקט GET או בקשת קטגוריה של GET), Cloud Storage מחזיר את התחביר של Amazon S3.
    • בעקבות בקשה ל-Cloud Storage להחיל רשימות ACL (לדוגמה, אובייקט PUT או בקשת קטגוריה של PUT), Cloud Storage מצפה לקבל תחביר של רשימות ACL של Amazon S3.

    בתרחיש העברה פשוטה, הכותרת Authorization משתמשת ב-AWS כמזהה החתימה, אבל עם מזהה הגישה שלכם ל-Cloud Storage HMAC.

    Authorization: AWS4-HMAC-SHA256 Credential=GOOG-ACCESS-ID/CREDENTIAL_SCOPE, SignedHeaders=SIGNED_HEADERS, Signature=SIGNATURE
    

    בדוגמה הבאה מוצגת בקשה של GET ל-Cloud Storage להחזרת רשימות ACL של אובייקט.

    GET europe/france/paris.jpg?acl HTTP/1.1
    Host: my-travel-maps.storage.s3nsapis.fr
    Date: Thu, 21 Feb 2019 23:50:10 GMT
    Content-Type: application/xml
    X-Amz-Date: 20190221T235010Z
    Authorization: AWS4-HMAC-SHA256 Credential=GOOGMC5PDPA5JLZYQMHQHRAX/20190221/region/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=29088b1d6dfeb2549f6ff67bc3744abb7e45475f0ad60400485805415bbfc534
    

    התגובה לבקשה כוללת את ה-ACL תוך שימוש בתחביר ACL של Amazon S3.

    <?xml version='1.0' encoding='UTF-8'?>
    <AccessControlPolicy>
        <Owner>
            <ID>00b4903a972faa8bcce9382686e9129676f1cd6e5def1f5663affc2ba4652490
            </ID>
            <DisplayName>OwnerName</DisplayName>
        </Owner>
        <AccessControlList>
            <Grant>
                <Grantee xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                    xsi:type='CanonicalUser'>
                    <ID>00b4903a972faa8bcce9382686e9129676f1cd6e5def1f5663affc2ba4652490</ID>
                    <DisplayName>UserName</DisplayName>
                </Grantee>
                <Permission>FULL_CONTROL</Permission>
            </Grant>
        </AccessControlList>
    </AccessControlPolicy>
    

    בדוגמה הבאה מוצגת בקשה של PUT ל-Cloud Storage להגדרת רשימות ACL של אובייקט. בדוגמה מוצג גוף בקשה עם תחביר ACL של Amazon S3.

    PUT europe/france/paris.jpg?acl HTTP/1.1
    Host: my-travel-maps.storage.s3nsapis.fr
    Date: Thu, 21 Feb 2019 23:50:10 GMT
    Content-Type: application/xml
    Content-Length: 337
    X-Amz-Date: 20190221T235010Z
    Authorization: AWS4-HMAC-SHA256 Credential=GOOGMC5PDPA5JLZYQMHQHRAX/20190221/region/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=29088b1d6dfeb2549f6ff67bc3744abb7e45475f0ad60400485805415bbfc534
    
    <?xml version='1.0' encoding='utf-8'?>
    <AccessControlPolicy>
      <AccessControlList>
        <Grant>
          <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="AmazonCustomerByEmail">
            <EmailAddress>example-service-account@example-project.s3ns.iam.gserviceaccount.com</EmailAddress>
          </Grantee>
          <Permission>FULL_CONTROL</Permission>
        </Grant>
      </AccessControlList>
    </AccessControlPolicy>
    

    לסיום, בתרחיש העברה פשוטה, אפשר להשתמש גם במזהה החתימה GOOG1 בכותרת של Authorization. במקרה כזה, צריך להשתמש בתחביר של ה-ACL של Cloud Storage ולוודא שכל הכותרות x-amz-* משתנות ל-x-goog-*. אומנם זה אפשרי, אבל מומלץ לבחור העברה מלאה כדי ליהנות מכל היתרונות של Cloud Storage.

    תמיכה בתאימות XML API עם Amazon S3

    לדיונים על יכולת פעולה הדדית של XML API, עיינו במאמר Stack Overflow באמצעות התג google-cloud-storage.