@@ -22,7 +22,6 @@ use crate::run::{
2222
2323use super :: logger:: GithubActionLogger ;
2424
25- #[ derive( Debug ) ]
2625pub struct GitHubActionsProvider {
2726 pub owner : String ,
2827 pub repository : String ,
@@ -39,6 +38,16 @@ pub struct GitHubActionsProvider {
3938
4039 /// Indicates whether the repository is private.
4140 is_repository_private : bool ,
41+
42+ /// OIDC configuration data necessary to request an OIDC token.
43+ ///
44+ /// If None, OIDC is not configured for this run.
45+ oidc_config : Option < OIDCTokenRequestData > ,
46+ }
47+
48+ struct OIDCTokenRequestData {
49+ request_url : String ,
50+ request_token : String ,
4251}
4352
4453impl GitHubActionsProvider {
@@ -139,6 +148,7 @@ impl TryFrom<&Config> for GitHubActionsProvider {
139148 repository_root_path,
140149 is_head_repo_fork,
141150 is_repository_private,
151+ oidc_config : None ,
142152 } )
143153 }
144154}
@@ -259,26 +269,27 @@ impl RunEnvironmentProvider for GitHubActionsProvider {
259269 Ok ( commit_hash)
260270 }
261271
262- /// Set the OIDC token for GitHub Actions if necessary
272+ /// Validate that the environment is correctly configured for OIDC usage.
263273 ///
264274 /// ## Logic
265- /// - If the user has explicitly set a token in the configuration (i.e. "static token"), do not override it, but display an info message .
275+ /// - If the user has explicitly set a token in the configuration (i.e. "static token"), inform the user that OIDC is available but do nothing .
266276 /// - Otherwise, check if the necessary environment variables are set to use OIDC.
267- /// - Then attempt to request an OIDC token.
268277 ///
278+ /// For Github Actions, there are two necessary environment variables:
279+ /// - `ACTIONS_ID_TOKEN_REQUEST_TOKEN`
280+ /// - `ACTIONS_ID_TOKEN_REQUEST_URL`
269281 /// If environment variables are not set, this could be because:
270282 /// - The user has misconfigured the workflow (missing `id-token` permission)
271283 /// - The run is from a public fork, in which case GitHub Actions does not provide these environment variables for security reasons.
272284 ///
273- ///
274285 /// ## Notes
275286 /// Retrieving the token requires that the workflow has the `id-token` permission enabled.
276287 ///
277288 /// Docs:
278289 /// - https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-with-reusable-workflows
279290 /// - https://docs.github.com/en/actions/concepts/security/openid-connect
280291 /// - https://docs.github.com/en/actions/reference/security/oidc#methods-for-requesting-the-oidc-token
281- async fn set_oidc_token ( & self , config : & mut Config ) -> Result < ( ) > {
292+ fn check_oidc_configuration ( & mut self , config : & Config ) -> Result < ( ) > {
282293 // Check if a static token is already set
283294 if config. token . is_some ( ) {
284295 info ! (
@@ -303,8 +314,8 @@ impl RunEnvironmentProvider for GitHubActionsProvider {
303314
304315 if self . is_repository_private {
305316 bail ! (
306- "Unable to retrieve OIDC token for authentication. \n \
307- Make sure your workflow has the `id-token: write` permission set. \n \
317+ "Unable to retrieve OIDC token for authentication.\n \
318+ Make sure your workflow has the `id-token: write` permission set.\n \
308319 See https://codspeed.io/docs/integrations/ci/github-actions/configuration#oidc-recommended"
309320 )
310321 }
@@ -319,34 +330,57 @@ impl RunEnvironmentProvider for GitHubActionsProvider {
319330 }
320331
321332 let request_url = request_url. unwrap ( ) ;
322- let request_url = format ! ( "{request_url}&audience={}" , self . get_oidc_audience( ) ) ;
323333 let request_token = request_token. unwrap ( ) ;
324334
325- let token = match OIDC_CLIENT
326- . get ( request_url)
327- . header ( "Accept" , "application/json" )
328- . header ( "Authorization" , format ! ( "Bearer {request_token}" ) )
329- . send ( )
330- . await
331- {
332- Ok ( response) => match response. json :: < OIDCResponse > ( ) . await {
333- Ok ( oidc_response) => oidc_response. value ,
335+ self . oidc_config = Some ( OIDCTokenRequestData {
336+ request_url,
337+ request_token,
338+ } ) ;
339+
340+ Ok ( ( ) )
341+ }
342+
343+ /// Request the OIDC token from GitHub Actions if necessary.
344+ ///
345+ /// All the validation has already been performed in `check_oidc_configuration`.
346+ /// So if the oidc_config is None, we simply return.
347+ async fn set_oidc_token ( & self , config : & mut Config ) -> Result < ( ) > {
348+ if let Some ( oidc_config) = & self . oidc_config {
349+ let request_url = format ! (
350+ "{}&audience={}" ,
351+ oidc_config. request_url,
352+ self . get_oidc_audience( )
353+ ) ;
354+
355+ let token = match OIDC_CLIENT
356+ . get ( request_url)
357+ . header ( "Accept" , "application/json" )
358+ . header (
359+ "Authorization" ,
360+ format ! ( "Bearer {}" , oidc_config. request_token) ,
361+ )
362+ . send ( )
363+ . await
364+ {
365+ Ok ( response) => match response. json :: < OIDCResponse > ( ) . await {
366+ Ok ( oidc_response) => oidc_response. value ,
367+ Err ( _) => None ,
368+ } ,
334369 Err ( _) => None ,
335- } ,
336- Err ( _) => None ,
337- } ;
370+ } ;
338371
339- if token. is_some ( ) {
340- debug ! ( "Successfully retrieved OIDC token for authentication." ) ;
341- config. set_token ( token) ;
342- } else if self . is_repository_private {
343- bail ! (
344- "Unable to retrieve OIDC token for authentication. \n \
345- Make sure your workflow has the `id-token: write` permission set. \n \
346- See https://codspeed.io/docs/integrations/ci/github-actions/configuration#oidc-recommended"
347- )
348- } else {
349- warn ! ( "Failed to retrieve OIDC token for authentication." ) ;
372+ if token. is_some ( ) {
373+ debug ! ( "Successfully retrieved OIDC token for authentication." ) ;
374+ config. set_token ( token) ;
375+ } else if self . is_repository_private {
376+ bail ! (
377+ "Unable to retrieve OIDC token for authentication. \n \
378+ Make sure your workflow has the `id-token: write` permission set. \n \
379+ See https://codspeed.io/docs/integrations/ci/github-actions/configuration#oidc-recommended"
380+ )
381+ } else {
382+ warn ! ( "Failed to retrieve OIDC token for authentication." ) ;
383+ }
350384 }
351385
352386 Ok ( ( ) )
@@ -641,6 +675,7 @@ mod tests {
641675 repository_root_path : "/home/work/my-repo" . into ( ) ,
642676 is_head_repo_fork : false ,
643677 is_repository_private : false ,
678+ oidc_config : None ,
644679 } ;
645680
646681 let run_part = github_actions_provider. get_run_provider_run_part ( ) . unwrap ( ) ;
@@ -685,6 +720,7 @@ mod tests {
685720 repository_root_path : "/home/work/my-repo" . into ( ) ,
686721 is_head_repo_fork : false ,
687722 is_repository_private : false ,
723+ oidc_config : None ,
688724 } ;
689725
690726 let run_part = github_actions_provider. get_run_provider_run_part ( ) . unwrap ( ) ;
@@ -738,6 +774,7 @@ mod tests {
738774 repository_root_path : "/home/work/my-repo" . into ( ) ,
739775 is_head_repo_fork : false ,
740776 is_repository_private : false ,
777+ oidc_config : None ,
741778 } ;
742779
743780 let run_part = github_actions_provider. get_run_provider_run_part ( ) . unwrap ( ) ;
@@ -789,6 +826,7 @@ mod tests {
789826 repository_root_path : "/home/work/my-repo" . into ( ) ,
790827 is_head_repo_fork : false ,
791828 is_repository_private : false ,
829+ oidc_config : None ,
792830 } ;
793831
794832 let run_part = github_actions_provider. get_run_provider_run_part ( ) . unwrap ( ) ;
0 commit comments