Search code examples
c#aws-lambda

C# lambda function can't find json files in the project


My lambda function uses a json credentials file (./credentials/myfile.json). Everything is working well on my computer or on lambdar test environment, but when I deploy it to AWS, it is enable to find the file, no matter its location.

Right now my files tree is:

myFunction

  • Credentials
    • backupuser_OAuth2_Credentials.json
    • origin_GDrive_Credentials.json
  • Utilities
    • GoogleDriveUtilities.cs
  • Function.cs
  • myFunction.csproj

And I am trying to access the credentials this way:

In Function.cs:

string originCredentialPath = "./Credentials/origin_GDrive_Credentials.json";

GoogleDriveUtilities origin_gdu = new GoogleDriveUtilities(originCredentialPath, "Origin account", 0); 

In my Utility class:

        string[] scopes = new string[]
        {
            //GDrive access
            DriveService.Scope.Drive,
        };

        GoogleCredential credential;

        try
        {
            using (var stream = new FileStream(credentialPath, FileMode.Open, FileAccess.Read))
            {
                credential = GoogleCredential.FromStream(stream)
                    .CreateScoped(DriveService.Scope.Drive);
            }

            driveService = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = applicationName,
            });

            Console.WriteLine("Google Drive service created: " + this.serviceName + ".");
            return driveService;
        }
        catch (Exception e)
        {
            Console.WriteLine("Error when creating Google Drive service:\n >>" + e);
        }
        return null;

On execution, I have the following error in cloudwatch logs:

System.IO.DirectoryNotFoundException: Could not find a part of the path '/var/task/Credentials/origin_GDrive_Credentials.json'.

Any clues?

Thank you!


Solution

  • Finally I fixed the issue by using AWS Secrets, in place of using files.

    As I was not able to find a way to give my lambda access to local files, I stored the json (credential informations) in AWS Secrets.

    I get the json data as below:

    string secretName = secretId;
    string region = "eu-west-3";
    
    IAmazonSecretsManager client = new AmazonSecretsManagerClient(RegionEndpoint.GetBySystemName(region));
    
    GetSecretValueRequest request = new GetSecretValueRequest
    {
          SecretId = secretName,
          VersionStage = "AWSCURRENT",
    };
    
    GetSecretValueResponse response;
    
    try
    {
          response = await client.GetSecretValueAsync(request);
    }
    catch (Exception e)
    {
          throw e;
    }
    
    var originCredentialJson = response.SecretString;
    

    I then accessed these data programmatically and updated my connection method as below:

    public DriveService initDriveServiceAccount(string json)
            {
                string[] scopes = new string[]
                {
                    //GDrive access
                    DriveService.Scope.Drive,
                };
    
                GoogleCredential credential;
    
                try
                {
                    credential = GoogleCredential.FromJson(json).CreateScoped(DriveService.Scope.Drive);
    
                    driveService = new DriveService(new BaseClientService.Initializer()
                    {
                        HttpClientInitializer = credential,
                        ApplicationName = applicationName,
                    });
    
                    context.Logger.LogInformation("Google Drive service created: " + this.serviceName + ".");
                    return driveService;
                }
                catch (Exception e)
                {
                    context.Logger.LogInformation("Error when creating Google Drive service:\n >>" + e);
                }
                return null;
            }