I am new to AWS and am going through the .NET Workloads on AWS App Runner course on the AWS website. I am in Module 3 and at the step where you test the application locally (step 5), located at https://aws.amazon.com/developer/language/net/badges-and-training/app-runner/module-three/. On this step under “3. Test the Weather Forecast action for Dallas”, I have gotten an Amazon.Runtime.AmazonServiceException in the app’s console window stating “Unable to get IAM security credentials from EC2 Instance Metadata Service” and the JSON returns an empty response in the browser after adding “/WeatherForecast?location=Dallas” to the URL as instructed.
Here is the stack trace from the console:
fail: HelloAppRunnerVpc.Controllers.WeatherForecastController[0]
90 Exception
Amazon.Runtime.AmazonServiceException: Unable to get IAM security credentials from EC2 Instance Metadata Service.
at Amazon.Runtime.DefaultInstanceProfileAWSCredentials.FetchCredentials()
at Amazon.Runtime.DefaultInstanceProfileAWSCredentials.GetCredentials()
at Amazon.Runtime.Internal.Util.SdkCache.CacheKey.Create(AmazonServiceClient client, Object cacheType)
at Amazon.Runtime.Internal.Util.SdkCache.GetCache[TKey,TValue](AmazonServiceClient client, Object cacheIdentifier, IEqualityComparer`1 keyComparer)
at Amazon.DynamoDBv2.DocumentModel.Table.GetTableDescriptionCache()
at Amazon.DynamoDBv2.DocumentModel.Table.LoadTable(IAmazonDynamoDB ddbClient, TableConfig config)
at HelloAppRunnerVpc.Controllers.WeatherForecastController.GetWeatherForecast(String location) in <my-redacted-path>HelloAppRunnerVpcControllersWeatherForecastController.cs:line 37
I have set up the AWS CLI and am able to successfully log in to an AWS profile that I made through the IAM identity center. In my /.aws/config file, I have the following credentials set (some are redacted):
[profile Kevin]
sso_session = MySession
sso_account_id = MyId
sso_role_name = AdministratorAccess
region = us-east-1
output = json
[sso-session MySession]
sso_start_url = MyUrl
sso_region = us-east-1
sso_registration_scopes = sso:account:access
For good measure, I have also set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN variables with the values from the Amazon Access portal page that appears in my browser after signing in from the AWS CLI.
Here is the code provided from the lab shown here for convenience (WeatherForecastController.cs):
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;
using Microsoft.AspNetCore.Mvc;
namespace HelloAppRunnerVpc.Controllers;
[ApiController]
[Route("")]
public class WeatherForecastController : ControllerBase
{
static readonly RegionEndpoint region = RegionEndpoint.USEast1;
private readonly ILogger _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet("")]
public string GetHealthcheck()
{
return "Healthcheck: Healthy";
}
[HttpGet("WeatherForecast")]
public async Task<IEnumerable<WeatherForecast>> GetWeatherForecast(string location = "Dallas")
{
List<WeatherForecast> forecasts = new List<WeatherForecast>();
try
{
_logger.LogInformation($"00 enter GET, location = {location}");
var client = new AmazonDynamoDBClient(region);
Table table = Table.LoadTable(client, "Weather");
var filter = new ScanFilter();
filter.AddCondition("Location", ScanOperator.Equal, location);
var scanConfig = new ScanOperationConfig()
{
Filter = filter,
Select = SelectValues.SpecificAttributes,
AttributesToGet = new List<string> { "Location", "Timestamp", "TempC", "TempF", "Summary" }
};
_logger.LogInformation($"10 table.Scan");
Search search = table.Scan(scanConfig);
List<Document> matches;
do
{
_logger.LogInformation($"20 table.GetNextSetAsync");
matches = await search.GetNextSetAsync();
foreach (var match in matches)
{
forecasts.Add(new WeatherForecast
{
Date = Convert.ToDateTime(match["Timestamp"]),
TemperatureC = Convert.ToInt32(match["TempC"]),
TemperatureF = Convert.ToInt32(match["TempF"]),
Summary = Convert.ToString(match["Summary"])
});
}
} while (!search.IsDone);
_logger.LogInformation($"30 exited results loop");
}
catch (Exception ex)
{
_logger.LogError(ex, "90 Exception");
}
_logger.LogInformation($"99 returning {forecasts.Count} results");
return forecasts.ToArray();
}
}
I have also made the required changes to the WeatherForecast class as well (also shown here for convenience):
namespace HelloAppRunnerVpc;
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF { get; set; }
public string? Summary { get; set; }
}
What step(s) should I take to resolve this exception? It’s my understanding that credentials are obtained automatically after signing in to your AWS profile in the CLI and that the AWS .NET SDK uses the default profile if none are specified in the code. Will I be able to use the default profile if I sign out of my current profile in the CLI? If not, should I add my profile info in the code for now to make the lab work? If not, what else could I try to successfully receive data from the created table? I checked my table in DynamoDB and it is present and made correctly.