use std::collections::HashMap; use std::cell::RefCell; use std::default::Default; use std::collections::BTreeMap; use serde_json as json; use std::io; use std::fs; use std::mem; use std::thread::sleep; use crate::client; // ############## // UTILITIES ### // ############ // ######## // HUB ### // ###### /// Central instance to access all CloudSecurityToken related resource activities /// /// # Examples /// /// Instantiate a new hub /// /// ```test_harness,no_run /// extern crate hyper; /// extern crate hyper_rustls; /// extern crate yup_oauth2 as oauth2; /// extern crate google_sts1 as sts1; /// use sts1::api::GoogleIdentityStsV1ExchangeTokenRequest; /// use sts1::{Result, Error}; /// # async fn dox() { /// use std::default::Default; /// use oauth2; /// use sts1::CloudSecurityToken; /// /// // Get an ApplicationSecret instance by some means. It contains the `client_id` and /// // `client_secret`, among other things. /// let secret: oauth2::ApplicationSecret = Default::default(); /// // Instantiate the authenticator. It will choose a suitable authentication flow for you, /// // unless you replace `None` with the desired Flow. /// // Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about /// // what's going on. You probably want to bring in your own `TokenStorage` to persist tokens and /// // retrieve them from storage. /// let auth = yup_oauth2::InstalledFlowAuthenticator::builder( /// secret, /// yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect, /// ).build().await.unwrap(); /// let mut hub = CloudSecurityToken::new(hyper::Client::builder().build(hyper_rustls::HttpsConnector::with_native_roots()), auth); /// // As the method needs a request, you would usually fill it with the desired information /// // into the respective structure. Some of the parts shown here might not be applicable ! /// // Values shown here are possibly random and not representative ! /// let mut req = GoogleIdentityStsV1ExchangeTokenRequest::default(); /// /// // You can configure optional parameters by calling the respective setters at will, and /// // execute the final call using `doit()`. /// // Values shown here are possibly random and not representative ! /// let result = hub.methods().token(req) /// .doit().await; /// /// match result { /// Err(e) => match e { /// // The Error enum provides details about what exactly happened. /// // You can also just use its `Debug`, `Display` or `Error` traits /// Error::HttpError(_) /// |Error::Io(_) /// |Error::MissingAPIKey /// |Error::MissingToken(_) /// |Error::Cancelled /// |Error::UploadSizeLimitExceeded(_, _) /// |Error::Failure(_) /// |Error::BadRequest(_) /// |Error::FieldClash(_) /// |Error::JsonDecodeError(_, _) => println!("{}", e), /// }, /// Ok(res) => println!("Success: {:?}", res), /// } /// # } /// ``` #[derive(Clone)] pub struct CloudSecurityToken<> { client: hyper::Client, hyper::body::Body>, auth: oauth2::authenticator::Authenticator>, _user_agent: String, _base_url: String, _root_url: String, } impl<'a, > client::Hub for CloudSecurityToken<> {} impl<'a, > CloudSecurityToken<> { pub fn new(client: hyper::Client, hyper::body::Body>, authenticator: oauth2::authenticator::Authenticator>) -> CloudSecurityToken<> { CloudSecurityToken { client, auth: authenticator, _user_agent: "google-api-rust-client/2.0.8".to_string(), _base_url: "https://sts.googleapis.com/".to_string(), _root_url: "https://sts.googleapis.com/".to_string(), } } pub fn methods(&'a self) -> MethodMethods<'a> { MethodMethods { hub: &self } } /// Set the user-agent header field to use in all requests to the server. /// It defaults to `google-api-rust-client/2.0.8`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { mem::replace(&mut self._user_agent, agent_name) } /// Set the base url to use in all requests to the server. /// It defaults to `https://sts.googleapis.com/`. /// /// Returns the previously set base url. pub fn base_url(&mut self, new_base_url: String) -> String { mem::replace(&mut self._base_url, new_base_url) } /// Set the root url to use in all requests to the server. /// It defaults to `https://sts.googleapis.com/`. /// /// Returns the previously set root url. pub fn root_url(&mut self, new_root_url: String) -> String { mem::replace(&mut self._root_url, new_root_url) } } // ############ // SCHEMAS ### // ########## /// Request message for ExchangeToken. /// /// # Activities /// /// This type is used in activities, which are methods you may call on this type or where this type is involved in. /// The list links the activity name, along with information about where it is used (one of *request* and *response*). /// /// * [token](MethodTokenCall) (request) /// #[derive(Default, Clone, Debug, Serialize, Deserialize)] pub struct GoogleIdentityStsV1ExchangeTokenRequest { /// The full resource name of the identity provider; for example: `//iam.googleapis.com/projects//workloadIdentityPools//providers/`. Required when exchanging an external credential for a Google access token. pub audience: Option, /// Required. The grant type. Must be `urn:ietf:params:oauth:grant-type:token-exchange`, which indicates a token exchange. #[serde(rename="grantType")] pub grant_type: Option, /// A set of features that Security Token Service supports, in addition to the standard OAuth 2.0 token exchange, formatted as a serialized JSON object of Options. pub options: Option, /// Required. An identifier for the type of requested security token. Must be `urn:ietf:params:oauth:token-type:access_token`. #[serde(rename="requestedTokenType")] pub requested_token_type: Option, /// The OAuth 2.0 scopes to include on the resulting access token, formatted as a list of space-delimited, case-sensitive strings. Required when exchanging an external credential for a Google access token. pub scope: Option, /// Required. The input token. This token is a either an external credential issued by a workload identity pool provider, or a short-lived access token issued by Google. If the token is an OIDC JWT, it must use the JWT format defined in [RFC 7523](https://tools.ietf.org/html/rfc7523), and the `subject_token_type` must be `urn:ietf:params:oauth:token-type:jwt`. The following headers are required: - `kid`: The identifier of the signing key securing the JWT. - `alg`: The cryptographic algorithm securing the JWT. Must be `RS256`. The following payload fields are required. For more information, see [RFC 7523, Section 3](https://tools.ietf.org/html/rfc7523#section-3): - `iss`: The issuer of the token. The issuer must provide a discovery document at the URL `/.well-known/openid-configuration`, where `` is the value of this field. The document must be formatted according to section 4.2 of the [OIDC 1.0 Discovery specification](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse). - `iat`: The issue time, in seconds, since the Unix epoch. Must be in the past. - `exp`: The expiration time, in seconds, since the Unix epoch. Must be less than 48 hours after `iat`. Shorter expiration times are more secure. If possible, we recommend setting an expiration time less than 6 hours. - `sub`: The identity asserted in the JWT. - `aud`: Configured by the mapper policy. The default value is the service account's unique ID. Example header: ``` { "alg": "RS256", "kid": "us-east-11" } ``` Example payload: ``` { "iss": "https://accounts.google.com", "iat": 1517963104, "exp": 1517966704, "aud": "113475438248934895348", "sub": "113475438248934895348", "my_claims": { "additional_claim": "value" } } ``` If `subject_token` is for AWS, it must be a serialized `GetCallerIdentity` token. This token contains the same information as a request to the AWS [`GetCallerIdentity()`](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity) method, as well as the AWS [signature](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html) for the request information. Use Signature Version 4. Format the request as URL-encoded JSON, and set the `subject_token_type` parameter to `urn:ietf:params:aws:token-type:aws4_request`. The following parameters are required: - `url`: The URL of the AWS STS endpoint for `GetCallerIdentity()`, such as `https://sts.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15`. Regional endpoints are also supported. - `method`: The HTTP request method: `POST`. - `headers`: The HTTP request headers, which must include: - `Authorization`: The request signature. - `x-amz-date`: The time you will send the request, formatted as an [ISO8601 Basic](https://docs.aws.amazon.com/general/latest/gr/sigv4_elements.html#sigv4_elements_date) string. This value is typically set to the current time and is used to help prevent replay attacks. - `host`: The hostname of the `url` field; for example, `sts.amazonaws.com`. - `x-goog-cloud-target-resource`: The full, canonical resource name of the workload identity pool provider, with or without an `https:` prefix. To help ensure data integrity, we recommend including this header in the `SignedHeaders` field of the signed request. For example: //iam.googleapis.com/projects//locations//workloadIdentityPools//providers/ https://iam.googleapis.com/projects//locations//workloadIdentityPools//providers/ If you are using temporary security credentials provided by AWS, you must also include the header `x-amz-security-token`, with the value set to the session token. The following example shows a `GetCallerIdentity` token: ``` { "headers": [ {"key": "x-amz-date", "value": "20200815T015049Z"}, {"key": "Authorization", "value": "AWS4-HMAC-SHA256+Credential=$credential,+SignedHeaders=host;x-amz-date;x-goog-cloud-target-resource,+Signature=$signature"}, {"key": "x-goog-cloud-target-resource", "value": "//iam.googleapis.com/projects//locations//workloadIdentityPools//providers/"}, {"key": "host", "value": "sts.amazonaws.com"} . ], "method": "POST", "url": "https://sts.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15" } ``` You can also use a Google-issued OAuth 2.0 access token with this field to obtain an access token with new security attributes applied, such as a Credential Access Boundary. In this case, set `subject_token_type` to `urn:ietf:params:oauth:token-type:access_token`. If an access token already contains security attributes, you cannot apply additional security attributes. #[serde(rename="subjectToken")] pub subject_token: Option, /// Required. An identifier that indicates the type of the security token in the `subject_token` parameter. Supported values are `urn:ietf:params:oauth:token-type:jwt`, `urn:ietf:params:aws:token-type:aws4_request`, and `urn:ietf:params:oauth:token-type:access_token`. #[serde(rename="subjectTokenType")] pub subject_token_type: Option, } impl client::RequestValue for GoogleIdentityStsV1ExchangeTokenRequest {} /// Response message for ExchangeToken. /// /// # Activities /// /// This type is used in activities, which are methods you may call on this type or where this type is involved in. /// The list links the activity name, along with information about where it is used (one of *request* and *response*). /// /// * [token](MethodTokenCall) (response) /// #[derive(Default, Clone, Debug, Serialize, Deserialize)] pub struct GoogleIdentityStsV1ExchangeTokenResponse { /// An OAuth 2.0 security token, issued by Google, in response to the token exchange request. Tokens can vary in size, depending in part on the size of mapped claims, up to a maximum of 12288 bytes (12 KB). Google reserves the right to change the token size and the maximum length at any time. pub access_token: Option, /// The amount of time, in seconds, between the time when the access token was issued and the time when the access token will expire. This field is absent when the `subject_token` in the request is a Google-issued, short-lived access token. In this case, the access token has the same expiration time as the `subject_token`. pub expires_in: Option, /// The token type. Always matches the value of `requested_token_type` from the request. pub issued_token_type: Option, /// The type of access token. Always has the value `Bearer`. pub token_type: Option, } impl client::ResponseResult for GoogleIdentityStsV1ExchangeTokenResponse {} // ################### // MethodBuilders ### // ################# /// A builder providing access to all free methods, which are not associated with a particular resource. /// It is not used directly, but through the `CloudSecurityToken` hub. /// /// # Example /// /// Instantiate a resource builder /// /// ```test_harness,no_run /// extern crate hyper; /// extern crate hyper_rustls; /// extern crate yup_oauth2 as oauth2; /// extern crate google_sts1 as sts1; /// /// # async fn dox() { /// use std::default::Default; /// use oauth2; /// use sts1::CloudSecurityToken; /// /// let secret: oauth2::ApplicationSecret = Default::default(); /// let auth = yup_oauth2::InstalledFlowAuthenticator::builder( /// secret, /// yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect, /// ).build().await.unwrap(); /// let mut hub = CloudSecurityToken::new(hyper::Client::builder().build(hyper_rustls::HttpsConnector::with_native_roots()), auth); /// // Usually you wouldn't bind this to a variable, but keep calling *CallBuilders* /// // like `token(...)` /// // to build up your call. /// let rb = hub.methods(); /// # } /// ``` pub struct MethodMethods<'a> where { hub: &'a CloudSecurityToken<>, } impl<'a> client::MethodsBuilder for MethodMethods<'a> {} impl<'a> MethodMethods<'a> { /// Create a builder to help you perform the following task: /// /// Exchanges a credential for a Google OAuth 2.0 access token. The token asserts an external identity within a workload identity pool, or it applies a Credential Access Boundary to a Google access token. When you call this method, do not send the `Authorization` HTTP header in the request. This method does not require the `Authorization` header, and using the header can cause the request to fail. /// /// # Arguments /// /// * `request` - No description provided. pub fn token(&self, request: GoogleIdentityStsV1ExchangeTokenRequest) -> MethodTokenCall<'a> { MethodTokenCall { hub: self.hub, _request: request, _delegate: Default::default(), _additional_params: Default::default(), } } } // ################### // CallBuilders ### // ################# /// Exchanges a credential for a Google OAuth 2.0 access token. The token asserts an external identity within a workload identity pool, or it applies a Credential Access Boundary to a Google access token. When you call this method, do not send the `Authorization` HTTP header in the request. This method does not require the `Authorization` header, and using the header can cause the request to fail. /// /// A builder for the *token* method. /// It is not used directly, but through a `MethodMethods` instance. /// /// # Example /// /// Instantiate a resource method builder /// /// ```test_harness,no_run /// # extern crate hyper; /// # extern crate hyper_rustls; /// # extern crate yup_oauth2 as oauth2; /// # extern crate google_sts1 as sts1; /// use sts1::api::GoogleIdentityStsV1ExchangeTokenRequest; /// # async fn dox() { /// # use std::default::Default; /// # use oauth2; /// # use sts1::CloudSecurityToken; /// /// # let secret: oauth2::ApplicationSecret = Default::default(); /// # let auth = yup_oauth2::InstalledFlowAuthenticator::builder( /// # secret, /// # yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect, /// # ).build().await.unwrap(); /// # let mut hub = CloudSecurityToken::new(hyper::Client::builder().build(hyper_rustls::HttpsConnector::with_native_roots()), auth); /// // As the method needs a request, you would usually fill it with the desired information /// // into the respective structure. Some of the parts shown here might not be applicable ! /// // Values shown here are possibly random and not representative ! /// let mut req = GoogleIdentityStsV1ExchangeTokenRequest::default(); /// /// // You can configure optional parameters by calling the respective setters at will, and /// // execute the final call using `doit()`. /// // Values shown here are possibly random and not representative ! /// let result = hub.methods().token(req) /// .doit().await; /// # } /// ``` pub struct MethodTokenCall<'a> where { hub: &'a CloudSecurityToken<>, _request: GoogleIdentityStsV1ExchangeTokenRequest, _delegate: Option<&'a mut dyn client::Delegate>, _additional_params: HashMap, } impl<'a> client::CallBuilder for MethodTokenCall<'a> {} impl<'a> MethodTokenCall<'a> { /// Perform the operation you have build so far. pub async fn doit(mut self) -> client::Result<(hyper::Response, GoogleIdentityStsV1ExchangeTokenResponse)> { use std::io::{Read, Seek}; use hyper::header::{CONTENT_TYPE, CONTENT_LENGTH, AUTHORIZATION, USER_AGENT, LOCATION}; use client::ToParts; let mut dd = client::DefaultDelegate; let mut dlg: &mut dyn client::Delegate = match self._delegate { Some(d) => d, None => &mut dd }; dlg.begin(client::MethodInfo { id: "sts.token", http_method: hyper::Method::POST }); let mut params: Vec<(&str, String)> = Vec::with_capacity(3 + self._additional_params.len()); for &field in ["alt"].iter() { if self._additional_params.contains_key(field) { dlg.finished(false); return Err(client::Error::FieldClash(field)); } } for (name, value) in self._additional_params.iter() { params.push((&name, value.clone())); } params.push(("alt", "json".to_string())); let mut url = self.hub._base_url.clone() + "v1/token"; let key = dlg.api_key(); match key { Some(value) => params.push(("key", value)), None => { dlg.finished(false); return Err(client::Error::MissingAPIKey) } } let url = url::Url::parse_with_params(&url, params).unwrap(); let mut json_mime_type: mime::Mime = "application/json".parse().unwrap(); let mut request_value_reader = { let mut value = json::value::to_value(&self._request).expect("serde to work"); client::remove_json_null_values(&mut value); let mut dst = io::Cursor::new(Vec::with_capacity(128)); json::to_writer(&mut dst, &value).unwrap(); dst }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); loop { request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let client = &self.hub.client; dlg.pre_request(); let mut req_builder = hyper::Request::builder().method(hyper::Method::POST).uri(url.clone().into_string()) .header(USER_AGENT, self.hub._user_agent.clone()); let request = req_builder .header(CONTENT_TYPE, format!("{}", json_mime_type.to_string())) .header(CONTENT_LENGTH, request_size as u64) .body(hyper::body::Body::from(request_value_reader.get_ref().clone())); client.request(request.unwrap()).await }; match req_result { Err(err) => { if let client::Retry::After(d) = dlg.http_error(&err) { sleep(d); continue; } dlg.finished(false); return Err(client::Error::HttpError(err)) } Ok(mut res) => { if !res.status().is_success() { let res_body_string = client::get_body_as_string(res.body_mut()).await; let json_server_error = json::from_str::(&res_body_string).ok(); let server_error = json::from_str::(&res_body_string) .or_else(|_| json::from_str::(&res_body_string).map(|r| r.error)) .ok(); if let client::Retry::After(d) = dlg.http_failure(&res, json_server_error, server_error) { sleep(d); continue; } dlg.finished(false); return match json::from_str::(&res_body_string){ Err(_) => Err(client::Error::Failure(res)), Ok(serr) => Err(client::Error::BadRequest(serr)) } } let result_value = { let res_body_string = client::get_body_as_string(res.body_mut()).await; match json::from_str(&res_body_string) { Ok(decoded) => (res, decoded), Err(err) => { dlg.response_json_decode_error(&res_body_string, &err); return Err(client::Error::JsonDecodeError(res_body_string, err)); } } }; dlg.finished(true); return Ok(result_value) } } } } /// /// Sets the *request* property to the given value. /// /// Even though the property as already been set when instantiating this call, /// we provide this method for API completeness. pub fn request(mut self, new_value: GoogleIdentityStsV1ExchangeTokenRequest) -> MethodTokenCall<'a> { self._request = new_value; self } /// The delegate implementation is consulted whenever there is an intermediate result, or if something goes wrong /// while executing the actual API request. /// /// It should be used to handle progress information, and to implement a certain level of resilience. /// /// Sets the *delegate* property to the given value. pub fn delegate(mut self, new_value: &'a mut dyn client::Delegate) -> MethodTokenCall<'a> { self._delegate = Some(new_value); self } /// Set any additional parameter of the query string used in the request. /// It should be used to set parameters which are not yet available through their own /// setters. /// /// Please note that this method must not be used to set any of the known parameters /// which have their own setter method. If done anyway, the request will fail. /// /// # Additional Parameters /// /// * *$.xgafv* (query-string) - V1 error format. /// * *access_token* (query-string) - OAuth access token. /// * *alt* (query-string) - Data format for response. /// * *callback* (query-string) - JSONP /// * *fields* (query-string) - Selector specifying which fields to include in a partial response. /// * *key* (query-string) - API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token. /// * *oauth_token* (query-string) - OAuth 2.0 token for the current user. /// * *prettyPrint* (query-boolean) - Returns response with indentations and line breaks. /// * *quotaUser* (query-string) - Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. /// * *uploadType* (query-string) - Legacy upload protocol for media (e.g. "media", "multipart"). /// * *upload_protocol* (query-string) - Upload protocol for media (e.g. "raw", "multipart"). pub fn param(mut self, name: T, value: T) -> MethodTokenCall<'a> where T: AsRef { self._additional_params.insert(name.as_ref().to_string(), value.as_ref().to_string()); self } }