Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update rlclientlib and rl.net to support azure credential hooks #609

Merged
merged 19 commits into from
Aug 22, 2024

Conversation

v-jameslongo
Copy link
Collaborator

@v-jameslongo v-jameslongo commented Aug 9, 2024

Summary

This pull request introduces a factory for creating Azure credential providers used to retrieve Azure OAuth tokens. The changes provide default implementations when RL_LINK_AZURE_LIBS is enabled when building the library. Custom implementations may be provided by using the factory to register implementations of i_oauth_credentials_provider.

Additionally, the default implementations work for .NET but also allow for custom .NET OAuth implementations for custom OAuth token retrieval using the OAuthCredentialProvider class in rl.net.

Details

The azure_cred_provider_factory_t provides the necessary Azure credential implementation used by the library to retrieve Azure OAuth tokens. The following Azure credential providers are included:

  • azure_credentials_provider<azure::identity::client_secret_credential>: Provides Azure OAuth token using client secret.
  • azure_credentials_provider<azure::identity::managed_identity>: Provides Azure OAuth token using managed identity.
  • azure_credentials_provider<azure::identity::azure_cli>: Provides Azure OAuth token using Azure CLI.
  • azure_credentials_provider<azure::identity::default_credential>: Provides Azure OAuth token using default credential.

The default implementation of azure_credentials_provider<azure::identity::default_credential> is used if azure.oauth.credential.type is not defined.

Configuration

The following configuration keys are used to configure the Azure credential provider:

  • azure.oauth.credential.type: Specifies the type of Azure credential provider to use. Supported values:
    • CLIENT_SECRET: Uses azure_credentials_provider<azure::identity::client_secret_credential> to provide Azure OAuth token.
    • MANAGED_IDENTITY: Uses azure_credentials_provider<azure::identity::managed_identity> to provide Azure OAuth token.
    • AZURECLI: Uses azure_credentials_provider<azure::identity::azure_cli> to provide Azure OAuth token.
    • DEFAULT_CREDENTIAL: Uses azure_credentials_provider<azure::identity::default_credential> to provide Azure OAuth token.

Additional configuration keys for specific credential types:

  • CLIENT_SECRET:

    • azure.oauth.credential.clientid
    • azure.oauth.credential.tenantid
    • azure.oauth.credential.clientsecret
  • MANAGED_IDENTITY:

    • azure.oauth.credential.clientid
  • AZURECLI:

    • azure.oauth.credential.tenantid

Usage

To enable Azure OAuth token authentication, the following configuration keys may be set:

  • model.source: HTTP_MODEL_DATA_OAUTH_AZ
  • interaction.sender.implementation: INTERACTION_HTTP_API_SENDER_OAUTH_AZ
  • observation.sender.implementation: OBSERVATION_HTTP_API_SENDER_OAUTH_AZ
  • episode.sender.implementation: EPISODE_HTTP_API_SENDER_OAUTH_AZ

For custom implementations, register your implementations using the factory. Alternatively, see register_default_factories_callback if you prefer not to use the factory directly.

Register Default Factories

The register_default_factories_callback function can be called to register factories for retrieving auth tokens. This is useful when control over retrieving tokens is needed and can be provided by the application.

To enable this feature, the application must call this function prior to calling API methods that retrieve sender/receiver objects that require it. The configuration file should define some or all of the following keys:

  • model.source: HTTP_MODEL_DATA_OAUTH
  • episode.sender.implementation: EPISODE_HTTP_API_SENDER_OAUTH
  • interaction.sender.implementation: INTERACTION_HTTP_API_SENDER_OAUTH
  • observation.sender.implementation: OBSERVATION_HTTP_API_SENDER_OAUTH

NOTE: The defaults for the above keys are as follows:

  • If USE_AZURE_FACTORIES is NOT defined as part of the build:

    • model.source: NO_MODEL_DATA
    • episode.sender.implementation: EPISODE_FILE_SENDER
    • interaction.sender.implementation: INTERACTION_FILE_SENDER
    • observation.sender.implementation: OBSERVATION_FILE_SENDER
    • time_provider.implementation: CLOCK_TIME_PROVIDER
  • If USE_AZURE_FACTORIES is defined as part of the build:

    • model.source: AZURE_STORAGE_BLOB
    • episode.sender.implementation: EPISODE_EH_SENDER
    • interaction.sender.implementation: INTERACTION_EH_SENDER
    • observation.sender.implementation: OBSERVATION_EH_SENDER
    • time_provider.implementation: NULL_TIME_PROVIDER

See the rl_sim example application to see how to use this feature.

.NET Implementation

The .NET implementation includes the OAuthCredentialProvider class, which is used to provide OAuth tokens to the underlying rlclientlib library.

Summary of OAuthCredentialProvider Class

The OAuthCredentialProvider class is a static class used to provide OAuth tokens to the rlclientlib library. It is designed to be sufficient for most applications. To control the OAuth token retrieval process, you can subscribe to the OAuthTokenRequested event. This allows for handling different scopes and customizing the token retrieval process.

Example Usage
static class EntryPoints
{
    private static ManagedIdentityCredential managedIdentityCredential;

    private static void OnOAuthTokenRequest(object src, OAuthTokenRequestedEventArgs e)
    {
        try {
            var accessToken = managedIdentityCredential.GetToken(e.Scopes);
            e.Token = accessToken.Token;
            e.TokenExpirationTime = accessToken.ExpiresOn;
            e.ErrorCode = 0;
        }
        catch (AuthenticationFailedException) {
            e.ErrorCode = 4; // http_bad_status_code
        }
    }

    public static void Main(string[] args)
    {
        // some startup code is here; do not use anything that would invoke an OAuth token request
        var my_client_id = args[1];
        managedIdentityCredential = new ManagedIdentityCredential(my_client_id);
        // ...
        // setup the OAuthCredentialProvider
        OAuthCredentialProvider.OAuthTokenRequested += OnOAuthTokenRequest;
        // now OAuth requests are ready to be handled
    }
}

Notes

This update enhances the flexibility and configurability of Azure OAuth token retrieval by providing multiple credential provider options and allowing for custom implementations. The .NET implementation provides a static OAuthCredentialProvider class to handle OAuth token requests, which can be customized by subscribing to the OAuthTokenRequested event.

update rl_sim to use azure_credentials_provider with DefaultAzureCredential
added support for the azure_credentials_provider in rl.net.native and rl.net
added cmake checks for dotnet-t4
Copy link
Member

@rajan-chari rajan-chari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

added 2 new error code for failing to authenticate
updated items as per PR comments
@v-jameslongo
Copy link
Collaborator Author

Updated the PR with suggested changes.

  1. added the tracer to azure_credentials_provider.
  2. narrow the scope of the lock when calling creds->getToken()
  3. added trace logging in the credentials provider for rlclientlib and rl.net.native
  4. added additional comments
  5. updated some formatting with respect to brace placement.

Copy link
Member

@rajan-chari rajan-chari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

…ib debug suffixes as the Ninja builds.

update the rlnetnative import constant (removing the d suffix)
@v-jameslongo v-jameslongo enabled auto-merge (squash) August 9, 2024 21:50
@v-jameslongo v-jameslongo disabled auto-merge August 9, 2024 21:50
Copy link
Member

@rajan-chari rajan-chari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - except for cleanup mentioned

@v-jameslongo v-jameslongo enabled auto-merge (squash) August 21, 2024 18:29
@v-jameslongo v-jameslongo disabled auto-merge August 21, 2024 21:57
@v-jameslongo v-jameslongo merged commit e1b77f6 into master Aug 22, 2024
56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants