ydb-platform / ydb-rs-sdk

Apache License 2.0
48 stars 16 forks source link

Implement get credentials from environment #186

Closed MikhailNazarov closed 5 months ago

MikhailNazarov commented 5 months ago

Is is useful for cloud usage. For local running we can use service account auth, for serverless containers or vm - metadata

This mechanism is described at https://ydb.tech/docs/en/reference/ydb-sdk/auth:


The following algorithm that is the same for all SDKs applies:

    If the value of the YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS environment variable is set, the System Account Key authentication mode is used and the key is taken from the file whose name is specified in this variable.
    Otherwise, if the value of the YDB_ANONYMOUS_CREDENTIALS environment variable is set to 1, the anonymous authentication mode is used.
    Otherwise, if the value of the YDB_METADATA_CREDENTIALS environment variable is set to 1, the Metadata authentication mode is used.
    Otherwise, if the value of the YDB_ACCESS_TOKEN_CREDENTIALS environment variable is set, the Access token authentication mode is used, where the this variable value is passed.
    Otherwise, the Metadata authentication mode is used.

If the last step of the algorithm is selecting the Metadata mode, you can deploy a working application on VMs and in Yandex.Cloud Cloud Functions without setting any environment variables.

now for that scenario, we should write something like:

async fn init_ydb() -> Result<ydb::Client, AppError> {
    let connection_string = env::var("YDB_CONNECTION_STRING")?;
    let builder = ClientBuilder::new_from_connection_string(connection_string)?;

    let builder = if env::var("YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS").is_ok() {
        builder.with_credentials(ServiceAccountCredentials::from_env()?)
    } else {
        builder.with_credentials(YandexMetadata::from_url(
            "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token",
        )?)
    };
    let client = builder.client()?;
    // wait until the background initialization of the driver finishes
    client.wait().await?;
    Ok(client)
}

Docs points that

From inside the VM, the [metadata](https://yandex.cloud/en/docs/compute/concepts/vm-metadata) service is accessible at the IP address 169.254.169.254.

Therefore, we need set default url for YandexMetadata with this method equals to "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token" for access metadata service inside container even without specify any environment variables.