oracle / oci-typescript-sdk

Oracle Cloud Infrastructure SDK for TypeScript and JavaScript
https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/typescriptsdk.htm
Other
77 stars 54 forks source link

Instance Principal Authentication Error with Node v18+ #226

Closed sdoffen closed 12 months ago

sdoffen commented 1 year ago

We are attempting to use Instance Principle Authentication and have been informed by our Oracle representatives that the Oracle SDKs now support Node.js versions 18.x and 20.x (despite the documentation still clearly stating that only 14.x and 16.x are supported).

This is important because neither version 14.x nor 16.x of Node.js are supported versions anymore. In fact, in October 2023 version 18.x is scheduled to move from LTS to Maintenance, and version 20.x is scheduled to move from Current to LTS. We intend to build our applications on version 20.x, and update regularly when newer versions of Node.js become available.

Relevant Documentation

This is the documentation we have been referencing to set up and use Instance Principle Authentication.

Environment

The compute instance VM image we are using comes with Node.js v10.x installed by default. We installed the nvm command line tool to update the version of Node.js after each test.

Minimum Required Code

The only application dependencies are:

"dependencies": {
  "oci-common": "^2.69.0",
  "oci-objectstorage": "^2.69.0",
  "oci-sdk": "^2.69.0"
}

This is the entire code of the application:

const os = require("oci-objectstorage");
const common = require("oci-common");
(async () => {
    const provider = await new common.InstancePrincipalsAuthenticationDetailsProviderBuilder().build();
    const client = new os.ObjectStorageClient({
        authenticationDetailsProvider: provider
    });
    client.region = common.Region.US_ASHBURN_1;
    console.log("Getting the namespace...");
    const request = {};
    const response = await client.getNamespace(request);
    console.log(response);
})();

Result By Node.js Version

Node.js Version Result
10.x Pass
12.x Pass
14.x Pass
16.x Pass
18.17.1 Fail
20.5.1 Fail

Note that in each case, the only thing that changed is the version of Node.js being used. The package versions and the code sample remained the same.

Error Message and Attempted Solutions

Node.js versions 18.17.1 and 20.5.1 exhibit the same behavior. At first, the code reports the following error:

Call to Regions.values() without having contacted IMDS (Instance Metadata Service, only available on OCI instances); if you do need the region from IMDS, call Region.enableInstanceMetadata() before calling Region.values()
/home/opc/sdk-issue/node_modules/oci-common/lib/auth/abstract-federation-client-authenticated-details-provider-builder.js:206
                throw Error("Failed to autoDetectCertificatesUsingMetadataUrl. " + INSTANCE_PRINCIPAL_GENERIC_ERROR);
                      ^

Error: Failed to autoDetectCertificatesUsingMetadataUrl. Instance principals authentication can only be used on OCI compute instances. Please confirm this code is running on an OCI compute instance. See https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm for more info.
    at InstancePrincipalsAuthenticationDetailsProviderBuilder.<anonymous> (/home/opc/sdk-issue/node_modules/oci-common/lib/auth/abstract-federation-client-authenticated-details-provider-builder.js:206:23)
    at Generator.throw (<anonymous>)
    at rejected (/home/opc/sdk-issue/node_modules/oci-common/lib/auth/abstract-federation-client-authenticated-details-provider-builder.js:10:65)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Which seems to indicate that the heretofore unnecessary method call common.Region.enableInstanceMetadata() needs to occur before calling common.Region.values(). No problem, we update our code to add that line, and it now looks like this:

const os = require("oci-objectstorage");
const common = require("oci-common");
(async () => {
    await common.Region.enableInstanceMetadata(); // <-- new line
    const provider = await new common.InstancePrincipalsAuthenticationDetailsProviderBuilder().build();
    const client = new os.ObjectStorageClient({
        authenticationDetailsProvider: provider
    });
    client.region = common.Region.US_ASHBURN_1;
    console.log("Getting the namespace...");
    const request = {};
    const response = await client.getNamespace(request);
    console.log(response);
})();

Which, when run, produces this next error:

/home/opc/sdk-issue/node_modules/oci-common/lib/auth/abstract-federation-client-authenticated-details-provider-builder.js:206
                throw Error("Failed to autoDetectCertificatesUsingMetadataUrl. " + INSTANCE_PRINCIPAL_GENERIC_ERROR);
                      ^

Error: Failed to autoDetectCertificatesUsingMetadataUrl. Instance principals authentication can only be used on OCI compute instances. Please confirm this code is running on an OCI compute instance. See https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm for more info.
    at InstancePrincipalsAuthenticationDetailsProviderBuilder.<anonymous> (/home/opc/sdk-issue/node_modules/oci-common/lib/auth/abstract-federation-client-authenticated-details-provider-builder.js:206:23)
    at Generator.throw (<anonymous>)
    at rejected (/home/opc/sdk-issue/node_modules/oci-common/lib/auth/abstract-federation-client-authenticated-details-provider-builder.js:10:65)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
KartikShrikantHegde commented 1 year ago

@sdoffen Thanks for reporting the issue, we will take a look, investigate, and provide an update as soon as we can. Thanks.

KartikShrikantHegde commented 1 year ago

Hi @sdoffen , we have a fix for this issue. We are planning to roll it out next week (Sept 26th) in the public version of the SDK. Will provide an update once it's released.

y-chandra commented 1 year ago

We've released a new version of the SDK with the fix. Please use version 2.70.2 to test the above feature and let us know if this resolves the issue for you.

sdoffen commented 1 year ago

The code from the original issue now runs successfully with Node.js v20.5.1 using the 2.70.2 version of the libraries. I did not do any backwards compatibility testing with older versions of Node.

sdoffen commented 1 year ago

When I run the above code without this line:

await common.Region.enableInstanceMetadata();

I still get the error:

Call to Regions.values() without having contacted IMDS (Instance Metadata Service, only available on OCI instances); if you do need the region from IMDS, call Region.enableInstanceMetadata() before calling Region.values()

However, the code still returns the expected result.

Is there documentation that would have provided that detail other than this blog post (which does not have it)? https://blogs.oracle.com/developers/post/instance-and-resource-principal-authentication-with-the-oci-typescriptjavascript-sdk

y-chandra commented 1 year ago

The above message is not an error, it is an expected warning to let you know that if you want the region from IMDS to be included, then you need to call Region.enableInstanceMetadata() prior to calling Region.values()

y-chandra commented 1 year ago

can we close this ticket?

y-chandra commented 12 months ago

Closing this ticket, please feel free to reopen