如何在 .net Core 中设置 AWS 凭证

12

我需要调试一个关于 .net Core 和 AWS 的现有项目。 我们的项目在 AWS 实例上运行良好,但无法在本地运行。

首先,我们遇到了 AmazonServiceException: Unable to find credentials 的问题,但现在我们有了这条消息:AmazonClientException: No RegionEndpoint or ServiceURL configured。我认为这更好。

我们的配置: 在我们的应用程序中,我们有 3 个 appsettings.{env.EnvironmentName}.json(开发、本地和生产)。我们知道 VS 默认使用开发文件。 在我们的开发 appsettings 文件中,没有 AWS 对象,但在本地 appsettings 文件中,我们只有这个:

"AWS": {
      "Region": "ap-southeast-2"
}

我们没有任何web.config或其他json配置文件。

我们尝试创建一个凭据文件,如下:

[name of my IAM profile]
aws_access_key_id=accesskey
aws_secret_access_key=secretkey
region=ap-southeast-2

但我们并没有找到如何使用它。

我们尝试使用dotnet core run命令来运行该项目,并指定一些环境变量,例如:

export AWS_Region=ap-southeast-2
export AWS_ACCESS_KEY_ID=id
export AWS_SECRET_ACCESS_KEY=secret
export AWS_SESSION_TOKEN=token
export 
AWS_CREDENTIAL_FILE=/Users/user/Developer/exemple/nameproject/G$

但是出现了相同的错误。

Program.cs 文件:

var host = new WebHostBuilder()
    .UseKestrel(options => options.AddServerHeader = false)
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseIISIntegration()
    .UseStartup<Startup>()
    .UseUrls("http://*:9000")
    .CaptureStartupErrors(true)
    .Build();

host.Run();

启动文件(第一个函数):

public Startup(IHostingEnvironment env) {
        // Configuration override https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", false, true)
            .AddEnvironmentVariables();

        Configuration = builder.Build();

        // Shared startup configurator
        CommonStartup = new CommonStartup(env, Configuration);
    }
这是我们的问题: 我们项目的凭证在哪里或如何配置?
感谢您提前回答。

AWS SDK会自动尝试查找Access/Secret密钥,因此将它们放在app.config中就足够了。在app.config中,这些密钥需要被命名为"AWSAccessKey"和"AWSSecretKey"。 - Rajesh
谢谢你的回答,Rajesh。 问题是这个项目中没有appconfig,除了3个appsettings.{env.EnvironmentName}.json文件之外。 你能给我一个这个文件的例子吗? 默认情况下,该项目使用开发配置文件,我如何告诉它使用本地版本的appsettings? 提前感谢您的回答。 - Dorian Sanchez
由于您使用了 ConfigurationBuilder,只需将它们添加到您的 JSON 文件中,它们就应该能够流经其中。 - Rajesh
我尝试在我的appsettings文件中添加以下内容: "AWS": { "AccessKeyId": "myaccesskey", "SecretAccessKey": "mysecretkey", "Region": "ap-southeast-2" } 但是我收到了这个消息:donet意外退出(我使用的是mac电脑)... - Dorian Sanchez
5个回答

13

在AWS中,您可以创建IAM角色并配置其仅对其需要的资源(例如S3读/写、SES等)具有访问权限。然后,您可以将此角色附加到EC2实例。

如果您正在使用AWS SDK,请使用以下命令:

services.AddDefaultAWSOptions(Configuration.GetAWSOptions());
services.AddAWSService<IAmazonS3>();

它会自动为您处理权限。

对于本地开发,您可能想使用凭据文件。在您的appsettings.Local.json中,您将拥有一个类似于此设置的设置:

"AWS": {
  "Profile": "myprofilename",
  "Region": "eu-west-1",
  "ProfilesLocation": "C:\\Credentials.txt"
}

为了避免意外将凭证文件上传到源代码管理系统,您可能希望将其存储在项目之外。

Credentials.txt 文件示例:

[myprofilename]
aws_access_key_id=MY_ACCESS_KEY
aws_secret_access_key=MY_ACCESS_SECRET

设置环境

您可能希望服务器上的代码在每个环境中都是相同的 - 这样可以使部署和其他任务更加容易。您可以通过使用参数存储来存储每个 AWS 环境的所有配置来实现这一点。

我处理这个问题的方式是在 EC2 实例上使用“tag”来指定环境名称。然后,我使用该标签从参数存储中获取正确的配置。

在您的情况下,标签将是 environment=developmentenvironment=production

存储中的参数名称/键应与您要覆盖的 JSON appsettings 文件中的属性名称匹配。

它们看起来类似于:

/development/ConnectionStrings/Database
/development/MySettingGroup/MySetting
/production/ConnectionStrings/Database
/production/MySettingGroup/MySetting

我已经在 GitHub 上添加了一些代码来检查标签和参数等 - 如果它在本地运行,则默认为“LocalDevelopment”(那是我使用的约定 - 所以您需要将其更改为“Local”)并加载正确的 appsettings 文件。

https://github.com/secretorange/aws-aspnetcore-environment-startup

您需要在项目中使用的文件位于此处:

https://github.com/secretorange/aws-aspnetcore-environment-startup/tree/master/AWSBoot/Boot

使用 BootHelper,您的启动代码将类似于以下内容:

public static IWebHost BuildWebHost()
{
    // ===================================
    // Get the boot config from the server
    // ===================================
    var bootConfig = Task.Run(() => BootHelper.GetConfig()).Result;

    var webHost = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureAppConfiguration((context, config) =>
        {
            // !!! IMPORTANT !!!
            // Set the environment from boot config
            context.HostingEnvironment.EnvironmentName = bootConfig.Environment;

            config.AddJsonFile("appsettings.json", optional: true)
                    .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true);

            // !!! IMPORTANT !!!
            // If there are any parameters from the server
            // then we'll use them to override anything in the JSON files
            config.AddInMemoryCollection(bootConfig.Parameters);
        })
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();

    return webHost;
}

AWS中的IAM角色需要附加策略以授予对标签和参数等的访问权限,它们看起来类似于:
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Sid": "VisualEditor0",
          "Effect": "Allow",
          "Action": [
              "ec2:DescribeInstances",
              "tag:GetResources",
              "tag:GetTagValues",
              "tag:GetTagKeys"
          ],
          "Resource": "*"
      }
  ]
}


{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Sid": "VisualEditor0",
          "Effect": "Allow",
          "Action": "ssm:GetParametersByPath",
          "Resource": [
              "arn:aws:ssm:YOUR_ARN_HERE:parameter/development",
              "arn:aws:ssm:YOUR_ARN_HERE:parameter/development/*"
          ]
      }
  ]
}

设置可能会有些麻烦,但一旦设置好了,您就可以轻松地将所有机密信息保留在源代码控制之外,也可以通过创建新标记和参数来创建新环境(例如 Staging)。无需进行任何代码更改。
如果您愿意,您可以将某些配置保留在 appsettings.Production.json 中。这意味着如果您想要创建一个新环境,您需要创建一个新的 JSON 文件并部署新代码等。如果所有环境信息都在 AWS 中(即 Parameter Store)可能会更加清晰简洁。

7

我找到了一种仅使用appsettings.json文件中的值来配置AWS凭证的方法。如果有帮助,我将在下面详细介绍它。注意!这不是AWS推荐的方式,我只是针对特定用例需要它。

在此示例中,我需要AWS凭证(访问密钥ID和访问密钥)以及区域和其他一些SQS队列客户端的配置。该应用程序是一个.Net 5 Worker Service(它具有依赖注入和配置文件设置,与ASP.Net Core Web应用程序相同)。

以下是appsettings.json文件:

{
  "AwsSqsConfiguration": {
    "AWSAccessKey": "ACCESSKEYID",
    "AWSSecretKey": "SECRETKEY",
    "AWSRegion": "us-west-2",
    "AWSQueueUrl": "https://sqs.us-east-1.amazonaws.com/rest-of-queue-url",
    "AWSQueueServiceUrl": "http://sqs.us-east-1.amazonaws.com"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

这是针对配置节'AwsSqsConfiguration'的C# 9记录:
public record AwsSqsConfiguration (
        string AWSAccessKey = null,
        string AWSSecretKey = null,
        string AWSRegion = null,
        string AWSQueueUrl = null,
        string AWSQueueServiceUrl = null);

这是Program.cs类的代码(类似于ASP.Net Core Web应用程序的Startup.cs类)。请注意使用Amazon.Runtime.BasicAWSCredentials传递访问密钥和秘密密钥的用法。
using Amazon.Extensions.NETCore.Setup;
using Amazon.SQS;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using PlatformDeploymentService.Core.Factories;
using PlatformDeploymentService.Core.Interfaces;
using PlatformDeploymentService.Core.Models.Configuration;
using PlatformDeploymentService.Core.Services;

namespace PlatformDeploymentService.WorkerService
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, configuration) => {
                    configuration.Sources.Clear();
                    IHostEnvironment env = hostingContext.HostingEnvironment;
                    configuration
                        .SetBasePath(env.ContentRootPath)
                        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true)
                        .AddEnvironmentVariables();
                })
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker>();

                    var awsSqsConfiguration = new AwsSqsConfiguration();
                    hostContext.Configuration.GetSection(nameof(AwsSqsConfiguration)).Bind(awsSqsConfiguration);
                    AWSOptions awsOptions = new AWSOptions
                    {
                        Credentials = new Amazon.Runtime.BasicAWSCredentials(awsSqsConfiguration.AWSAccessKey, awsSqsConfiguration.AWSSecretKey),
                        Region = Amazon.RegionEndpoint.GetBySystemName(awsSqsConfiguration.AWSRegion)
                    };
                    services.AddDefaultAWSOptions(awsOptions);
                    services.AddSingleton<IAmazonSQS>(sp => new AmazonSQSClient(awsOptions.Credentials, new AmazonSQSConfig { ServiceURL = awsSqsConfiguration.AWSQueueServiceUrl }));
                });
    }
}

程序集 Program.cs 中使用的 Nuget 包的包引用:

<ItemGroup>
    <PackageReference Include="AWSSDK.Extensions.NETCore.Setup" Version="3.3.101" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
  </ItemGroup>

然后,无论您在何处需要 SQS Client 来排队消息或其他操作,都可以在构造函数中接收 IAmazonSQS 的实例,以便依赖注入可以注入它。

参考资料:


我忘了提到Nuget包AWSSDK.SQS(截至本文撰写时的版本为3.5.1.3)也被使用,以引用IAmazonSQS和AmazonSQSClient、AmazonSQSConfig等。 - Esteban Villegas
这似乎是在大费周折地撤销默认设置,只是为了以极少的好处重新构建一些相同的东西。 - undefined

3

1
但这是什么?"Profile": "local-test-profile"。如何在Windows PC上设置local-test-profile - Sampath
1
@norm,不需要将凭据存储在文件中,有没有一种直接从appsettings中读取的方法呢? - aman
与.NET Framework不同,没有全局单例来获取为您的应用程序创建的配置对象。 AWSSDK.Extensions.NETCore.Setup 的目的是将.NET Core配置系统与无法依赖于配置包或具有对配置对象的句柄的AWS SDK之间的差距进行桥接。 - Norm Johanson
1
@NormJohanson 在生产环境中应该怎么做?环境变量是前进的方向吗? - James Woodley

2
我选择使用 .net Core 2.0 而不是 1.1,并在 VS 中添加环境变量(ASPNETCORE_ENVIRONMENT、AWS_SECRET_ACCESS_KEY、AWS_ACCESS_KEY_ID、AWS_DEFAULT_REGION),现在它可以正常工作了!谢谢你的帮助,Rajesh。
但如果有人知道为什么现在可以工作,请提前在这里写下你的答案。

1
请问您是如何添加这些环境变量的? - Ertan Hasani
1
你可以用多种方式来实现。在 Visual Studio 中,有一个属性调试下的位置,你可以设置要拉取的环境变量。确保你在正确的项目下。另一种方法是将它们添加到系统的环境变量中以运行。如果你正在使用 Docker 或非 Windows 环境,并且仍然希望它在 CI(Jenkins)上运行,这是一个不错的选择。 - Ben

0

对我来说,环境变量丢失了。只需添加它,就可以正常工作了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接