Как подключиться к Yandex Cloud Storage через AWS S3 golang

К

Проблема

Если вы вдруг решили подключиться в Yandex Cloud Storage с помощью библиотеки golang aws, у вас могут возникнуть проблемы. Давайте попробуем разобраться.

Официальная документация

В документации от яндекса, есть пример, как мы можем подключиться к их хранилищу с помощью golang aws библиотеки.

Если вы пришли сюда, то скорее всего изучили уже ее и у вас ничего не получилось, но на всякий случай, вот ссылка на ее.

Вы можете столкнуться с двумя проблемами.

Проблема с «unknown endpoint requested»

У вас может возникнуть это ошибка, если вы указали регион как в документации, «ru-central1», попробуйте указать регион «us-east-1», то есть выглядеть это будет так:

customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		if service == s3.ServiceID && region == "us-east-1" {
			return aws.Endpoint{
				PartitionID:   "yc",
				URL:           "https://storage.yandexcloud.net",
				SigningRegion: "ru-central1",
			}, nil
		}
		return aws.Endpoint{}, fmt.Errorf("unknown endpoint requested")
	})

То есть в if блоке заменим регион на другой.

Проблема SignatureDoesNotMatch

После этого, вы скорее всего получите ошибку StatusCode: 403, RequestID: 42e13ec9e5a8e84f, HostID: , api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.

Дело в том, что яндекс документация предлагает вам хранить ключи в .aws папке, но мы не хотим их там хранить, а хотим прописать где-нибудь в конфиге, или использовать какой-нибудь другой метод.

Решение

Например, я сделал себе access и secret key, и хочу подключаться по ним. Поэтому мне надо добавить в LoadDefaultConfig метод, кроме WithEndpointResolverWithOptions, еще и WithCredentialsProvider, получается примерно так.

cfg, err := config.LoadDefaultConfig(
		context.TODO(),
		config.WithEndpointResolverWithOptions(customResolver),
		config.WithCredentialsProvider(
			&credentials.StaticCredentialsProvider{
				Value: aws.Credentials{
					AccessKeyID:     "AccessKeyID",
					SecretAccessKey: "SecretAccessKey",
				}}))

Вместо «AccessKeyID» и «SecretAccessKey» вам надо указать свой ключ и секрет, соответственно.

После этого у вас должен заработать ваш код

Итог

Итоговый код подключения у вас должен выглядеть так

func main() {
	customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		if service == s3.ServiceID && region == "us-east-1" {
			return aws.Endpoint{
				PartitionID:   "yc",
				URL:           "https://storage.yandexcloud.net",
				SigningRegion: "us-east-1",
			}, nil
		}
		return aws.Endpoint{}, fmt.Errorf("unknown endpoint requested")
	})

	cfg, err := config.LoadDefaultConfig(
		ctx,
		config.WithEndpointResolverWithOptions(customResolver),
		config.WithCredentialsProvider(
			&credentials.StaticCredentialsProvider{
				Value: aws.Credentials{
					AccessKeyID:     "AccessKeyID",
					SecretAccessKey: "SecretAccessKey",
				}}))
	client := s3.NewFromConfig(cfg)
	result, err := client.ListBuckets(context.TODO(), &s3.ListBucketsInput{})
	if err != nil {
		log.Fatal(err)
	}
	for _, bucket := range result.Buckets {
		log.Printf("bucket=%s creation time=%s", aws.ToString(bucket.Name), bucket.CreationDate.Format("2006-01-02 15:04:05 Monday"))
	}
}

Так же, вы можете указать другой провайдер.

Автор

Denis Pershin

Добавить комментарий