[CSHARP-3740] Add native support for AWS IAM Roles for service accounts, EKS in particular Created: 15/Jul/21  Updated: 28/Oct/23  Resolved: 22/Nov/22

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: None
Fix Version/s: 2.19.0

Type: New Feature Priority: Major - P3
Reporter: Backlog - Core Eng Program Management Team Assignee: Dmitry Lukyanov (Inactive)
Resolution: Fixed Votes: 3
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Issue split
split from DRIVERS-1746 Add native support for AWS IAM Roles ... Closed
Related
is related to CSHARP-4395 C# Driver caches AWS credentials assu... Closed
Quarter: FY23Q3
Case:
Upstream Changes Summary:

DRIVERS-1746:
Summary of required changes

  • Add support for AssumeRoleWithWebIdentity in AWS Auth
  • Add integration tests to verify usage
  • Use the credentials found in this document

Additional background

Please see https://github.com/mongodb/specifications/commit/bc4257fed21186ba9b53e2c0b7e92482da196882 for the specification change and https://github.com/mongodb/specifications/commit/cdd93a4c7639014c8837d34a3e26e408d7b14d5b for a clarification.

Please see https://github.com/mongodb/mongo-csharp-driver/commit/daa88998837aace9296b7c1f599c901f3cdac86f for a reference implementation in C#.

Integration test

Drivers are expected to add an integration test as described in the specification change


 Description   

DRIVERS Ticket Description
Script Target - If you can read this text, the script has failed


 Comments   
Comment by Githook User [ 22/Nov/22 ]

Author:

{'name': 'Dmitry Lukyanov', 'email': 'dmitry.lukyanov@mongodb.com', 'username': 'DmitryLukyanov'}

Message: CSHARP-3740: Add native support for AWS IAM Roles for service accounts, EKS in particular. (#947)
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/daa88998837aace9296b7c1f599c901f3cdac86f

Comment by Fernando Auresco [ 20/Jul/22 ]

@Jason Penniman we found an issue with our workaround, that is the connections in the server were never closed (i.e. the connections with expired credentials) and eventually we have reached a limit and the server stopped accepting new connections. We were not able to find out how to avoid this so we decided to rollback to using regular credentials and wait for an official implementation. The main issue is that once you create MongoClient, because there is no dispose or something like that, when you create a new MongoClient with updated cnn string (updated credentials) the old connection is still cached somewhere and kept open.

Anyway here is the relevant code to get the AWS Role temporary credentials and apply it to the cnn string in case you want to try:

using (var sts = new AmazonSecurityTokenServiceClient())
{
    var roleArn = Environment.GetEnvironmentVariable("AWS_ROLE_ARN");        if (roleArn == null)
    {
        throw new MongoDbSettingsException("Environment variable AWS_ROLE_ARN must be set when AWSAssumeIAMRole is true!");
    }        var roleTokenPath = Environment.GetEnvironmentVariable("AWS_WEB_IDENTITY_TOKEN_FILE");      if (roleTokenPath == null)
    {
        throw new MongoDbSettingsException("Environment variable AWS_WEB_IDENTITY_TOKEN_FILE must be set when AWSAssumeIAMRole is true!");
    }        if (!File.Exists(roleTokenPath))
    {
        throw new MongoDbSettingsException(string.Format("Could not find token file in AWS_WEB_IDENTITY_TOKEN_FILE path! ({0})", roleTokenPath));
    }        var roleTokenValue = File.ReadAllText(roleTokenPath);        var response = sts.AssumeRoleWithWebIdentityAsync(new AssumeRoleWithWebIdentityRequest() { RoleArn = roleArn, WebIdentityToken = roleTokenValue, RoleSessionName = "app" }).Result;        if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
    {
        _awsCredentials = response.Credentials;        if(_awsCredentialsRefreshTimer == null)
        {
            _awsCredentialsRefreshTimer = new Timer(AwsRefreshCredentials, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
        }        _log.LogInformation("AWS IAM Role temporary credentials expires at {0}", _awsCredentials.Expiration);               var awsCnnString = AddToConnectionString(settings.ConnectionString,  "authSource=%24external&authMechanism=MONGODB-AWS&authMechanismProperties=AWS_SESSION_TOKEN:{token}");                awsCnnString = AddConnectionPoolSettings(
                                awsCnnString.Replace("{user}", _awsCredentials.AccessKeyId)
                                    .Replace("{password}", Uri.EscapeDataString(_awsCredentials.SecretAccessKey))
                                    .Replace("{token}", Uri.EscapeDataString(_awsCredentials.SessionToken)));        return awsCnnString;
    }
    else
    {
        throw new MongoDbSettingsException(string.Format("Could not assume AWS IAM ROLE! [Status {0}]", response.HttpStatusCode));
    }
}

 

 

Comment by Dmitry Lukyanov (Inactive) [ 19/Jul/22 ]

Hey jason.penniman@na.linedata.com, we have plans to implement this, but it's not scheduled yet. Please follow DRIVERS-1746 for updates.

Comment by Jason Penniman [ 19/Jul/22 ]

@fauresco@satelital.com.br, we can't get IAM roles to work in EKS at all.  Do you have a working example I could take a look at? When we asked support, they said it was not supported, but it seams you have a viable workaround?

Comment by Fernando Auresco [ 29/Apr/22 ]

Thank you James!

For now, what I did is to have my base repository class to have a "Collection" property that will watch for the aws credentials expiration and refresh it if necessary, creating another MongoClient with updated credentials.

Comment by James Kovacs [ 29/Apr/22 ]

Hi, fauresco@satelital.com.br,

Thank you for reaching out about this issue. It is a problem that we are actively discussing how to solve in a consistent way across all drivers and the server. Please follow DRIVERS-1746 for updates on the overall effort. Once we have decided on an implementation strategy, you can follow this ticket for progress on the .NET/C# implementation.

Sincerely,
James

Comment by Fernando Auresco [ 29/Apr/22 ]

I was able to connect using the Kubernetes pod role reading the values from environment variables AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE then using this to call AWS SDK Secure Token Service AssumeRoleWithWebIdentity method. This returns TEMPORARY credentials which works (by default) for one hour. These credentails are then used in the MongoDb connection string.

The problem is that after the credentials expire, there is no way to call AssumeRoleWithWebIdentity to fetch new credentials. A similar issue is described here https://www.mongodb.com/community/forums/t/re-establish-aws-assumerole-connection/127067 (it is not EKS but the problem is the same).

It would be nice if the driver could deal with this automatically.

Generated at Wed Feb 07 21:46:10 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.