Skip to content

Commit

Permalink
Use client id from trusted issuer in oidc token verifier. (#12530)
Browse files Browse the repository at this point in the history
* Creating a verifier config with client id read from trusted issuer. This allow creating a config with different expected client id values, based on detected issuer in provided oidc token. Each client specific for oidc provider and application must use uniq audience value.

* Fix compile error.

* Fixed tests errors.

* cleanup

* Refactored NewTokenProcessor function. Extracted part responsible for validating and setting trusted issuer.
The issuer validation code is now a method on issuer type.

* Fixed tests. Removed testing error message, just expecting an error.
  • Loading branch information
dekiel authored Jan 13, 2025
1 parent 670774e commit afcccf8
Show file tree
Hide file tree
Showing 14 changed files with 490 additions and 234 deletions.
47 changes: 24 additions & 23 deletions cmd/oidc-token-verifier/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ type Logger interface {

type options struct {
token string
clientID string
trustedWorkflows []string
debug bool
oidcTokenExpirationTime int // OIDC token expiration time in minutes
}
Expand All @@ -41,13 +39,6 @@ func NewRootCmd() *cobra.Command {
It uses OIDC discovery to get the public keys and verify the token whenever the public keys are not cached or expired.`,
}
rootCmd.PersistentFlags().StringVarP(&opts.token, "token", "t", "", "OIDC token to verify")
// This flag should be enabled once we add support for it in the code.
// rootCmd.PersistentFlags().StringSliceVarP(&opts.trustedWorkflows, "trusted-workflows", "w", []string{}, "List of trusted workflows")
// err := rootCmd.MarkPersistentFlagRequired("trusted-workflows")
// if err != nil {
// panic(err)
// }
rootCmd.PersistentFlags().StringVarP(&opts.clientID, "client-id", "c", "image-builder", "OIDC token client ID, this is used to verify the audience claim in the token. The value should be the same as the audience claim value in the token.")
rootCmd.PersistentFlags().BoolVarP(&opts.debug, "debug", "d", false, "Enable debug mode")
rootCmd.PersistentFlags().IntVarP(&opts.oidcTokenExpirationTime, "oidc-token-expiration-time", "e", 10, "OIDC token expiration time in minutes")
return rootCmd
Expand Down Expand Up @@ -119,29 +110,32 @@ func (opts *options) verifyToken() error {
return err
}

// Print used options values.
logger.Infow("Using the following trusted workflows", "trusted-workflows", opts.trustedWorkflows)
logger.Infow("Using the following client ID", "client-id", opts.clientID)

// Create a new verifier config that will be used to verify the token.
// The clientID is used to verify the audience claim in the token.
verifyConfig, err := tioidc.NewVerifierConfig(logger, opts.clientID, tioidc.SkipExpiryCheck())
if err != nil {
return err
}
logger.Infow("Verifier config created", "config", verifyConfig)

// Create a new token processor
// It reads issuer from the token and verifies if the issuer is trusted.
// The tokenProcessor is a main object that is used to verify the token and extract the claim values.
// TODO(dekiel): add support for providing trusted issuers instead of using the value from the package.
tokenProcessor, err := tioidc.NewTokenProcessor(logger, tioidc.TrustedOIDCIssuers, opts.token, verifyConfig)
tokenProcessor, err := tioidc.NewTokenProcessor(logger, tioidc.TrustedOIDCIssuers, opts.token)
if err != nil {
return err
}

logger.Infow("Token processor created for trusted issuer", "issuer", tokenProcessor.Issuer())

// TODO (dekiel): implement writing output data to the file. This will give us separated clear output for a data and logs.
fmt.Printf("GITHUB_URL=%s\n", tokenProcessor.GetIssuer().GetGithubURL())

// Create a new verifier config that will be used to verify the token.
// The standard expiration check is skipped.
// We use custom expiration time check to allow longer token expiration time than the value in the token.
// The extended expiration time is needed due to Azure DevOps delays in starting the pipeline.
// The delay was causing the token to expire before the pipeline started.
verifierConfig, err := tokenProcessor.NewVerifierConfig(tioidc.SkipExpiryCheck())
if err != nil {
return err
}

logger.Infow("Verifier config created")

ctx := context.Background()
// Create a new provider using OIDC discovery to get the public keys.
// It uses the issuer from the token to get the OIDC discovery endpoint.
Expand All @@ -153,21 +147,28 @@ func (opts *options) verifyToken() error {

// Create a new verifier using the provider and the verifier config.
// The verifier is used to verify the token signature, expiration time and execute standard OIDC validation.
verifier, err := provider.NewVerifier(logger, verifyConfig, tioidc.WithExtendedExpiration(opts.oidcTokenExpirationTime))
// TODO (dekiel): Consider using verifier config as the only way to parametrize the verification process.
// The WithExtendedExpiration could be moved to the verifier config.
// The WithExtendedExpiration could disable the standard expiration check.
// This would allow to have a single place to configure the verification process.
verifier, err := provider.NewVerifier(logger, verifierConfig, tioidc.WithExtendedExpiration(opts.oidcTokenExpirationTime))
if err != nil {
return err
}

logger.Infow("New verifier created")

// Verify the token
token, err = verifier.Verify(ctx, opts.token)
if err != nil {
return err
}

logger.Infow("Token verified successfully")

// Create claims
claims := tioidc.NewClaims(logger)

logger.Infow("Verifying token claims")

// Pass the token to ValidateClaims
Expand Down
74 changes: 13 additions & 61 deletions pkg/oidc/mocks/mock_ClaimsInterface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/oidc/mocks/mock_ClaimsReader.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/oidc/mocks/mock_ProviderInterface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/oidc/mocks/mock_TokenInterface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/oidc/mocks/mock_TokenProcessorOption.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions pkg/oidc/mocks/mock_TokenVerifierInterface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions pkg/oidc/mocks/mock_Verifier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/oidc/mocks/mock_VerifierConfigOption.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/oidc/mocks/mock_VerifierProvider.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/oidc/mocks/mock_loggerInterface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit afcccf8

Please sign in to comment.