

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 Vagrant 实例上使用 SDK for Ruby
<a name="cookbooks-101-opsworks-s3-vagrant"></a>

**重要**  
该 AWS OpsWorks Stacks 服务于 2024 年 5 月 26 日终止，新客户和现有客户均已禁用。我们强烈建议客户尽快将其工作负载迁移到其他解决方案。如果您对迁移有疑问，请通过 re [AWS : Post 或通过 Pre](https://repost.aws/) mium Su [AWS pp](https://aws.amazon.com/support) ort 与 AWS 支持 团队联系。

本主题介绍在 Vagrant 实例上运行的配方如何使用[适用于 Ruby 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/)从 Amazon S3 下载文件。在开始之前，您必须先拥有一组 AWS 证书（访问密钥和私有访问密钥），允许配方访问 Amazon S3。

**重要**  
强烈建议您不要将根账户凭证用于此目的。而是使用适当的策略创建用户并为该配方提供这些凭证。  
注意不要将证书（甚至是 IAM 用户证书）放在可公开访问的位置，例如将包含证书的文件上传到公共存储库或 Bitbucket 存储库。 GitHub 这样做会暴露您的凭证，并可能危及您的账户安全。  
 在 EC2 Amazon EC2 实例上运行的配方可以使用更好的方法，即 IAM 角色，如中所述[在 OpsWorks Stacks Linux 实例上使用适用于 Ruby 的 SDK](cookbooks-101-opsworks-s3-opsworks.md)。  
发送到 Amazon S3 存储桶的内容可能包含客户内容。有关删除敏感数据的更多信息，请参阅[如何清空 S3 存储桶？](https://docs.aws.amazon.com/AmazonS3/latest/userguide/empty-bucket.html)或[如何删除 S3 存储桶？](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html)。

如果您还没有适当的 用户，可创建一个此类用户，如下所示。有关更多信息，请参阅[什么是 IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/Introduction.html)。

**警告**  
IAM 用户具有长期凭证，这会带来安全风险。为帮助减轻这种风险，我们建议仅向这些用户提供执行任务所需的权限，并在不再需要这些用户时将其移除。

**若要创建 IAM 用户**

1. 登录 AWS 管理控制台 并打开 IAM 控制台，网址为[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)。

1. 在导航窗格中，选择 **Users** 并在必要时选择 **Add users** 以创建新的管理用户。

1. 在 **设置权限 ** 页面上，选择 **直接附加策略**。

1. 在 **Permissions policies** 搜索框中键入 **S3** 以显示 Amazon S3 策略。

   选择**亚马逊 S3 ReadOnlyAccess**。如果您愿意，可以指定授予更广泛权限的策略，例如 **AmazonS3 FullAccess**，但标准做法是仅授予所需的权限。在此示例中，配方将仅下载一个文件，因此只读访问权就够用了。

1. 选择**下一步**。

1. 选择 **Create user**。

1. 为您的用户创建访问密钥。有关创建访问密钥的更多信息，请参阅 *IAM 用户指南* 中的[管理 IAM 用户的访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html)。

接下来，您必须提供要下载的文件。此示例假定您将名为 `myfile.txt` 的文件放入新创建的名为 `cookbook_bucket` 的 S3 存储桶中。

**提供要下载的文件**

1. 使用以下文本创建一个名为 `myfile.txt` 的文件并将该文件保存在工作站上的方便位置。

   ```
   This is the file that you just downloaded from Amazon S3.
   ```

1. 在 [Amazon S3 控制台](https://console.aws.amazon.com/s3/)上，在 `cookbook_bucket`Standard 区域中创建一个名为 的存储桶并将 `myfile.txt` 上传到此存储桶。

按如下所示设置说明书。

**设置说明书**

1. 在 `opsworks_cookbooks` 中创建一个名为 `s3bucket` 的目录并导航到该目录。

1. 按照[示例 1：安装软件包](cookbooks-101-basics-packages.md)中所述初始化并配置 Test Kitchen。

1. 使用以下内容替换 `.kitchen.yml` 中的文本。

   ```
   ---
   driver:
     name: vagrant
   
   provisioner:
     name: chef_solo
     environments_path: ./environments
   
   platforms:
     - name: ubuntu-14.04
   
   suites:
     - name: s3bucket
       provisioner:
         solo_rb:
           environment: test
       run_list:
         - recipe[s3bucket::default]
       attributes:
   ```

1. 将以下两个目录添加到 `s3bucket`：`recipes` 和 `environments`。

1. 使用以下 `default_attributes` 部分创建名为 `test.json` 的环境文件，将 `access_key` 和 `secret_key` 值替换为您用户的对应密钥。将文件保存到说明书的 `environments` 文件夹。

   ```
   {
     "default_attributes" : {
       "cookbooks_101" : {
         "access_key": "AKIAIOSFODNN7EXAMPLE",
         "secret_key" : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
       }
     },
     "chef_type" : "environment",
     "json_class" : "Chef::Environment"
   }
   ```

可通过多种方法为实例上运行的配方提供凭证。关键注意事项是限制意外公开密钥和危及账户安全的机会。为此，建议不要在代码中使用显式密钥值。此示例将密钥值放入节点对象中，这将通过使用节点语法而不是公开文本值来允许配方引用密钥值。您必须拥有根特权才能访问节点对象，这限制了公开密钥的可能性。有关更多信息，请参阅[管理 AWS 访问密钥的最佳实践](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html)。

**注意**  
请注意，此示例使用嵌套属性，并将 `cookbooks_101` 作为第一个元素。如果节点对象中有其他 `access_key` 或 `secret_key` 属性，此实践将限制名称冲突的可能性。

以下配方从 `myfile.text` 存储桶下载 `cookbook_bucket`。

```
gem_package "aws-sdk ~> 3" do
  action :install
end

ruby_block "download-object" do
  block do
    require 'aws-sdk'

    s3 = Aws::S3::Client.new(
          :access_key_id => "#{node['cookbooks_101']['access_key']}",
          :secret_access_key => "#{node['cookbooks_101']['secret_key']}")

    myfile = s3.bucket['cookbook_bucket'].objects['myfile.txt']
    Dir.chdir("/tmp")
    File.open("myfile.txt", "w") do |f|
      f.write(myfile.read)
      f.close
    end
  end
  action :run
end
```

此配方的第一部分安装 SDK for Ruby (gem 程序包)。[gem\$1package](https://docs.chef.io/chef/resources.html#gem-package) 资源安装将由配方或其他应用程序使用的 gem。

**注意**  
您的实例通常有两个 Ruby 实例（通常版本不同）。一个是由 Chef 客户端使用的专用实例。另一个由实例上运行的应用程序和配方使用。安装 gem 程序包时务必了解此区别，因为提供了两种用于安装 gem 的资源 ([gem\$1package](https://docs.chef.io/chef/resources.html#gem-package) 和 [chef\$1gem](https://docs.chef.io/chef/resources.html#chef-gem))。如果应用程序或配方使用 gem 程序包，则使用 `gem_package` 安装它。`chef_gem` 仅适用于由 Chef 客户端使用的 gem 程序包。

其余配方为 [ruby\$1block](https://docs.chef.io/chef/resources.html#ruby-block) 资源，其中包含下载文件的 Ruby 代码。您可能会认为，由于配方是一个 Ruby 应用程序，因此您可以直接将代码放入配方。但是，Chef 运行将在执行任何资源之前编译所有代码。如果您将示例代码直接放入配方中，则 Ruby 在执行 `require 'aws-sdk'` 资源之前会尝试解析 `gem_package` 语句。由于 SDK for Ruby 尚未安装，因此编译将失败。

在执行资源之前不会编译 `ruby_block` 资源中的代码。在此示例中，将在 `ruby_block` 资源安装完 SDK for Ruby;之后执行 `gem_package` 资源，因此代码将成功运行。

`ruby_block` 中的代码将按如下所示运行。

1. 创建新的 [https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3.html](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3.html) 对象，该对象提供服务接口。

   访问密钥和私有密钥是通过引用存储在节点对象中的值来指定的。

1. 调用 `S3` 对象的 `bucket.objects` 关联，这将返回名为 `myfile` 的表示 `myfile.txt` 的 [https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html) 对象。

1. 使用 `Dir.chdir` 将工作目录设置为 `/tmp`。

1. 打开名为 `myfile.txt` 的文件，将 `myfile` 的内容写入此文件，然后关闭此文件。

**运行配方**

1. 使用示例配方创建一个名为 `default.rb` 的文件，并将该文件保存到 `recipes` 目录。

1. 运行 `kitchen converge`。

1. 运行 `kitchen login` 以登录实例，然后运行 `ls /tmp`。您应该会看到 `myfile.txt` 以及几个 Test Kitchen 文件和目录。

   ```
   vagrant@s3bucket-ubuntu-1204:~$ ls /tmp
   install.sh  kitchen  myfile.txt  stderr
   ```

   您还可运行 `cat /tmp/myfile.txt` 验证文件内容是否正确。

完成后，运行 `kitchen destroy` 以终止实例。