使用scala时,lambda的AWS凭据无法正常工作

时间:2022-02-22 23:07:05

AWS lambda function does not work when attempting to work with credentials provided using the DefaultCredentialProvider.

尝试使用使用DefaultCredentialProvider提供的凭据时,AWS lambda函数不起作用。

I need to pass the credentials to S3 for it to run.

我需要将凭据传递给S3才能运行。

Code

def initializeAwsCredentials():AWSCredentials = {
    var credentials: AWSCredentials  = null
    try {
      credentials = new ProfileCredentialsProvider().getCredentials
    } catch {
      case e: Exception => {
        throw new AmazonClientException(
          "Cannot load the credentials from the credential profiles file. " +
            "Please make sure that your credentials file is at the correct " +
            "location (~/.aws/credentials), and is in valid format.",
          e);
      }

    }
    return credentials
  }

 def buildS3API(credentials: AWSCredentials): AmazonS3 = {
  new AmazonS3Client(credentials)
}

// inside handle request
val credentials = initializeAwsCredentials()
println("Credetials have been retrieved successfully")

println("Build S3 API using the constructor provided")
val s3 = buildS3API(credentials)
s3.setRegion(region)
println("S3 API is now available")

Error

错误

{
  "errorMessage": "Cannot load the credentials from the credential profiles file. Please make sure that your credentials file is at the correct location (~/.aws/credentials), and is in valid format.",
  "errorType": "com.amazonaws.AmazonClientException",
  "stackTrace": [
    "example.Main$.initializeAwsCredentials(Hello.scala:52)",
    "example.Main$.handleRequest(Hello.scala:125)",
    "example.Main.handleRequest(Hello.scala)",
    "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
    "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
    "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
    "java.lang.reflect.Method.invoke(Method.java:498)"
  ],
  "cause": {
    "errorMessage": "java.lang.NullPointerException",
    "errorType": "java.lang.NullPointerException",
    "stackTrace": [
      "com.amazonaws.auth.profile.ProfilesConfigFile.<init>(ProfilesConfigFile.java:143)",
      "com.amazonaws.auth.profile.ProfilesConfigFile.<init>(ProfilesConfigFile.java:132)",
      "com.amazonaws.auth.profile.ProfilesConfigFile.<init>(ProfilesConfigFile.java:99)",
      "com.amazonaws.auth.profile.ProfileCredentialsProvider.getCredentials(ProfileCredentialsProvider.java:135)",
      "example.Main$.initializeAwsCredentials(Hello.scala:45)",
      "example.Main$.handleRequest(Hello.scala:125)",
      "example.Main.handleRequest(Hello.scala)",
      "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
      "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
      "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
      "java.lang.reflect.Method.invoke(Method.java:498)"
    ]
  }
}

Update

更新

Using the InstanceProfileCredentialsProvider instead throws the error:

使用InstanceProfileCredentialsProvider会抛出错误:

val provider: InstanceProfileCredentialsProvider = new InstanceProfileCredentialsProvider()
credentials = provider.getCredentials()

gives me the error:

给我错误:

"cause": {
    "errorMessage": "Unable to load credentials from Amazon EC2 metadata service",
    "errorType": "com.amazonaws.AmazonClientException",
    "stackTrace": [
      "com.amazonaws.auth.InstanceProfileCredentialsProvider.handleError(InstanceProfileCredentialsProvider.java:244)",
      "com.amazonaws.auth.InstanceProfileCredentialsProvider.loadCredentials(InstanceProfileCredentialsProvider.java:225)",
      "com.amazonaws.auth.InstanceProfileCredentialsProvider.getCredentials(InstanceProfileCredentialsProvider.java:124)",
      "example.Main$.initializeAwsCredentials(Hello.scala:46)",
      "example.Main$.handleRequest(Hello.scala:126)",
      "example.Main.handleRequest(Hello.scala)",
      "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
      "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
      "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
      "java.lang.reflect.Method.invoke(Method.java:498)"
    ],
    "cause": {
      "errorMessage": "Connection refused (Connection refused)",
      "errorType": "java.net.ConnectException",
      "stackTrace": [
        "java.net.PlainSocketImpl.socketConnect(Native Method)",
        "java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)",
        "java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)",
        "java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)",
        "java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)",
        "java.net.Socket.connect(Socket.java:589)",
        "sun.net.NetworkClient.doConnect(NetworkClient.java:175)",
        "sun.net.www.http.HttpClient.openServer(HttpClient.java:463)",
        "sun.net.www.http.HttpClient.openServer(HttpClient.java:558)",
        "sun.net.www.http.HttpClient.<init>(HttpClient.java:242)",
        "sun.net.www.http.HttpClient.New(HttpClient.java:339)",
        "sun.net.www.http.HttpClient.New(HttpClient.java:357)",
        "sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1202)",
        "sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1138)",
        "sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1032)",
        "sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:966)",
        "com.amazonaws.internal.EC2MetadataClient.readResource(EC2MetadataClient.java:90)",
        "com.amazonaws.internal.EC2MetadataClient.getDefaultCredentials(EC2MetadataClient.java:55)",
        "com.amazonaws.auth.InstanceProfileCredentialsProvider.loadCredentials(InstanceProfileCredentialsProvider.java:186)",
        "com.amazonaws.auth.InstanceProfileCredentialsProvider.getCredentials(InstanceProfileCredentialsProvider.java:124)",
        "example.Main$.initializeAwsCredentials(Hello.scala:46)",
        "example.Main$.handleRequest(Hello.scala:126)",
        "example.Main.handleRequest(Hello.scala)",
        "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
        "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
        "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
        "java.lang.reflect.Method.invoke(Method.java:498)"
      ]
    }
  }
}

Configuring the following as environment variables when using lambda also fails:

使用lambda时将以下配置为环境变量也会失败:

Lambda was unable to configure your environment variables because the 
environment variables you have provided contains reserved keys that are 
currently not supported for modification. Reserved keys used in this 
request: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY

2 个解决方案

#1


1  

I am not sure you need an explicit credentials provider. Inside the AWS Lambda the credentials are automatically provided via the role the lambda can assume. I know I never did it explicitly.

我不确定您是否需要显式凭据提供程序。在AWS Lambda内部,凭证可以通过lambda可以承担的角色自动提供。我知道我从来没有明确地做过。

http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-lambda.html

http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-lambda.html

#2


0  

For Lambda functions you will want to use an IAM role for credentials. Then you would either use the DefaultAWSCredentialsProviderChain or InstanceProfileCredentialsProvider to retrieve the credentials from the IAM role.

对于Lambda函数,您将需要使用IAM角色作为凭据。然后,您可以使用DefaultAWSCredentialsProviderChain或InstanceProfileCredentialsProvider从IAM角色检索凭据。

Class InstanceProfileCredentialsProvider

Class InstanceProfileCredentialsProvider

Here is an example using InstanceProfileCredentialsProvider:

以下是使用InstanceProfileCredentialsProvider的示例:

   AWSCredentialsProvider credentialsProvider = null;
    try {
        credentialsProvider = new InstanceProfileCredentialsProvider();
        // Verify we can fetch credentials
        credentialsProvider.getCredentials();
        System.out.println("Obtained credentials.");
    } catch (AmazonClientException e) {
        System.out.println("Unable to obtain credentials", e);
        return -1;
    }

    System.out.println("Using credentials with access key id: " + credentialsProvider.getCredentials().getAWSAccessKeyId());

#1


1  

I am not sure you need an explicit credentials provider. Inside the AWS Lambda the credentials are automatically provided via the role the lambda can assume. I know I never did it explicitly.

我不确定您是否需要显式凭据提供程序。在AWS Lambda内部,凭证可以通过lambda可以承担的角色自动提供。我知道我从来没有明确地做过。

http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-lambda.html

http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-lambda.html

#2


0  

For Lambda functions you will want to use an IAM role for credentials. Then you would either use the DefaultAWSCredentialsProviderChain or InstanceProfileCredentialsProvider to retrieve the credentials from the IAM role.

对于Lambda函数,您将需要使用IAM角色作为凭据。然后,您可以使用DefaultAWSCredentialsProviderChain或InstanceProfileCredentialsProvider从IAM角色检索凭据。

Class InstanceProfileCredentialsProvider

Class InstanceProfileCredentialsProvider

Here is an example using InstanceProfileCredentialsProvider:

以下是使用InstanceProfileCredentialsProvider的示例:

   AWSCredentialsProvider credentialsProvider = null;
    try {
        credentialsProvider = new InstanceProfileCredentialsProvider();
        // Verify we can fetch credentials
        credentialsProvider.getCredentials();
        System.out.println("Obtained credentials.");
    } catch (AmazonClientException e) {
        System.out.println("Unable to obtain credentials", e);
        return -1;
    }

    System.out.println("Using credentials with access key id: " + credentialsProvider.getCredentials().getAWSAccessKeyId());