Skip to content

Commit

Permalink
Split off a separate InstanceMetadataAuthenticator
Browse files Browse the repository at this point in the history
  • Loading branch information
jneem committed Dec 12, 2022
1 parent 143f41d commit 4439918
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 56 deletions.
14 changes: 7 additions & 7 deletions src/application_default_credentials.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
use crate::error::Error;
use crate::types::TokenInfo;
use http::Uri;
use hyper::client::connect::Connection;
use std::error::Error as StdError;
use http::Uri;
use tokio::io::{AsyncRead, AsyncWrite};
use tower_service::Service;

/// Provide options for the Application Default Credential Flow, mostly used for testing
/// Provide options for the Instance Metadata Flow, mostly used for testing
#[derive(Default, Clone, Debug)]
pub struct ApplicationDefaultCredentialsFlowOpts {
pub struct InstanceMetadataFlowOpts {
/// Used as base to build the url during token request from GCP metadata server
pub metadata_url: Option<String>,
}

pub struct ApplicationDefaultCredentialsFlow {
pub struct InstanceMetadataFlow {
metadata_url: String,
}

impl ApplicationDefaultCredentialsFlow {
pub(crate) fn new(opts: ApplicationDefaultCredentialsFlowOpts) -> Self {
impl InstanceMetadataFlow {
pub(crate) fn new(opts: InstanceMetadataFlowOpts) -> Self {
let metadata_url = opts.metadata_url.unwrap_or_else(|| "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token".to_string());
ApplicationDefaultCredentialsFlow { metadata_url }
InstanceMetadataFlow { metadata_url }
}

pub(crate) async fn token<S, T>(
Expand Down
65 changes: 51 additions & 14 deletions src/authenticator.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! Module containing the core functionality for OAuth2 Authentication.
use crate::application_default_credentials::{
ApplicationDefaultCredentialsFlow, ApplicationDefaultCredentialsFlowOpts,
};
use crate::application_default_credentials::{InstanceMetadataFlow, InstanceMetadataFlowOpts};
use crate::authenticator_delegate::{DeviceFlowDelegate, InstalledFlowDelegate};
use crate::authorized_user::{AuthorizedUserFlow, AuthorizedUserSecret};
use crate::device::DeviceFlow;
Expand Down Expand Up @@ -302,10 +300,10 @@ impl ServiceAccountAuthenticator {
/// # #[cfg(all(any(feature = "hyper-rustls", feature = "hyper-tls"), feature = "service_account"))]
/// # async fn foo() {
/// # use yup_oauth2::ApplicationDefaultCredentialsAuthenticator;
/// # use yup_oauth2::ApplicationDefaultCredentialsFlowOpts;
/// # use yup_oauth2::InstanceMetadataFlowOpts;
/// # use yup_oauth2::authenticator::ApplicationDefaultCredentialsTypes;
///
/// let opts = ApplicationDefaultCredentialsFlowOpts::default();
/// let opts = InstanceMetadataFlowOpts::default();
/// let authenticator = ApplicationDefaultCredentialsAuthenticator::builder(opts)
/// .await
/// .build()
Expand Down Expand Up @@ -357,15 +355,15 @@ impl ApplicationDefaultCredentialsAuthenticator {
doc(cfg(any(feature = "hyper-rustls", feature = "hyper-tls")))
)]
pub async fn builder(
opts: ApplicationDefaultCredentialsFlowOpts,
opts: InstanceMetadataFlowOpts,
) -> ApplicationDefaultCredentialsTypes<DefaultHyperClient> {
Self::with_client(opts, DefaultHyperClient).await
}

/// Use the builder pattern to deduce which model of authenticator should be used and allow providing a hyper client
#[cfg(feature = "service_account")]
pub async fn with_client<C>(
opts: ApplicationDefaultCredentialsFlowOpts,
opts: InstanceMetadataFlowOpts,
client: C,
) -> ApplicationDefaultCredentialsTypes<C>
where
Expand Down Expand Up @@ -398,7 +396,7 @@ where
/// User account authentication
AuthorizedUser(AuthenticatorBuilder<C, AuthorizedUserFlow>),
/// GCE Instance Metadata based authenticator signature
InstanceMetadata(AuthenticatorBuilder<C, ApplicationDefaultCredentialsFlowOpts>),
InstanceMetadata(AuthenticatorBuilder<C, InstanceMetadataFlowOpts>),
}

impl<C> ApplicationDefaultCredentialsTypes<C>
Expand All @@ -416,6 +414,46 @@ where
}
}

/// Create an authenticator that uses a metadata server to access service account credentials.
///
/// Note that this is the final fallback in the Application Default Credentials flow,
/// so you may want to use [`ApplicationDefaultCredentialsAuthenticator`] instead of
/// using this directly.
///
/// ```
/// # #[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))]
/// # async fn foo() {
/// # use yup_oauth2::authenticator::AuthorizedUserAuthenticator;
/// # let secret = yup_oauth2::read_authorized_user_secret("/tmp/foo").await.unwrap();
/// let authenticator = yup_oauth2::InstanceMetadataAuthenticator::builder(Default::default())
/// .build()
/// .await
/// .expect("failed to create authenticator");
/// # }
/// ```
pub struct InstanceMetadataAuthenticator;
impl InstanceMetadataAuthenticator {
/// Use the builder pattern to create an Authenticator that uses a a metadata server.
#[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))]
#[cfg_attr(
yup_oauth2_docsrs,
doc(cfg(any(feature = "hyper-rustls", feature = "hyper-tls")))
)]
pub fn builder(
opts: InstanceMetadataFlowOpts,
) -> AuthenticatorBuilder<DefaultHyperClient, InstanceMetadataFlowOpts> {
Self::with_client(opts, DefaultHyperClient)
}

/// Construct a new Authenticator that uses the metadata server and the provided http client.
pub fn with_client<C>(
opts: InstanceMetadataFlowOpts,
client: C,
) -> AuthenticatorBuilder<C, InstanceMetadataFlowOpts> {
AuthenticatorBuilder::new(opts, client)
}
}

/// Create an authenticator that uses an authorized user credentials.
/// ```
/// # #[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))]
Expand Down Expand Up @@ -762,18 +800,17 @@ impl<C> AuthenticatorBuilder<C, ServiceAccountFlowOpts> {
}
}

impl<C> AuthenticatorBuilder<C, ApplicationDefaultCredentialsFlowOpts> {
impl<C> AuthenticatorBuilder<C, InstanceMetadataFlowOpts> {
/// Create the authenticator.
pub async fn build(self) -> io::Result<Authenticator<C::Connector>>
where
C: HyperClientBuilder,
{
let application_default_credential_flow =
ApplicationDefaultCredentialsFlow::new(self.auth_flow);
let instance_metadata_flow = InstanceMetadataFlow::new(self.auth_flow);
Self::common_build(
self.hyper_client_builder,
self.storage_type,
AuthFlow::ApplicationDefaultCredentialsFlow(application_default_credential_flow),
AuthFlow::ApplicationDefaultCredentialsFlow(instance_metadata_flow),
)
.await
}
Expand Down Expand Up @@ -828,7 +865,7 @@ impl<C> AuthenticatorBuilder<C, AccessTokenFlow> {
}
mod private {
use crate::access_token::AccessTokenFlow;
use crate::application_default_credentials::ApplicationDefaultCredentialsFlow;
use crate::application_default_credentials::InstanceMetadataFlow;
use crate::authenticator::{AsyncRead, AsyncWrite, Connection, Service, StdError, Uri};
use crate::authorized_user::AuthorizedUserFlow;
use crate::device::DeviceFlow;
Expand All @@ -845,7 +882,7 @@ mod private {
#[cfg(feature = "service_account")]
ServiceAccountFlow(ServiceAccountFlow),
ServiceAccountImpersonationFlow(ServiceAccountImpersonationFlow),
ApplicationDefaultCredentialsFlow(ApplicationDefaultCredentialsFlow),
ApplicationDefaultCredentialsFlow(InstanceMetadataFlow),
AuthorizedUserFlow(AuthorizedUserFlow),
AccessTokenFlow(AccessTokenFlow),
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,13 @@ pub use crate::authenticator::ServiceAccountAuthenticator;
pub use crate::authenticator::{
AccessTokenAuthenticator, ApplicationDefaultCredentialsAuthenticator,
AuthorizedUserAuthenticator, DeviceFlowAuthenticator, InstalledFlowAuthenticator,
ServiceAccountImpersonationAuthenticator,
InstanceMetadataAuthenticator, ServiceAccountImpersonationAuthenticator,
};

pub use crate::helper::*;
pub use crate::installed::InstalledFlowReturnMethod;

pub use crate::application_default_credentials::ApplicationDefaultCredentialsFlowOpts;
pub use crate::application_default_credentials::InstanceMetadataFlowOpts;
#[cfg(feature = "service_account")]
pub use crate::service_account::ServiceAccountKey;

Expand Down
Loading

0 comments on commit 4439918

Please sign in to comment.