Проблема
Если вы вдруг решили подключиться в 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")) } }
Так же, вы можете указать другой провайдер.