mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2026-10-18 04:41:19 +02:00
feat(entra): add Workload Identity support for Entra ID (#2902)
This commit is contained in:
@@ -489,6 +489,7 @@ type LegacyProvider struct {
|
||||
AzureTenant string `flag:"azure-tenant" cfg:"azure_tenant"`
|
||||
AzureGraphGroupField string `flag:"azure-graph-group-field" cfg:"azure_graph_group_field"`
|
||||
EntraIDAllowedTenants []string `flag:"entra-id-allowed-tenant" cfg:"entra_id_allowed_tenants"`
|
||||
EntraIDFederatedTokenAuth bool `flag:"entra-id-federated-token-auth" cfg:"entra_id_federated_token_auth"`
|
||||
BitbucketTeam string `flag:"bitbucket-team" cfg:"bitbucket_team"`
|
||||
BitbucketRepository string `flag:"bitbucket-repository" cfg:"bitbucket_repository"`
|
||||
GitHubOrg string `flag:"github-org" cfg:"github_org"`
|
||||
@@ -552,6 +553,7 @@ func legacyProviderFlagSet() *pflag.FlagSet {
|
||||
flagSet.String("azure-tenant", "common", "go to a tenant-specific or common (tenant-independent) endpoint.")
|
||||
flagSet.String("azure-graph-group-field", "", "configures the group field to be used when building the groups list(`id` or `displayName`. Default is `id`) from Microsoft Graph(available only for v2.0 oidc url). Based on this value, the `allowed-group` config values should be adjusted accordingly. If using `id` as group field, `allowed-group` should contains groups IDs, if using `displayName` as group field, `allowed-group` should contains groups name")
|
||||
flagSet.StringSlice("entra-id-allowed-tenant", []string{}, "list of tenants allowed for MS Entra ID multi-tenant application")
|
||||
flagSet.Bool("entra-id-federated-token-auth", false, "enable oAuth client authentication with federated token projected by Azure Workload Identity plugin, instead of client secret.")
|
||||
flagSet.String("bitbucket-team", "", "restrict logins to members of this team")
|
||||
flagSet.String("bitbucket-repository", "", "restrict logins to user with access to this repository")
|
||||
flagSet.String("github-org", "", "restrict logins to members of this organisation")
|
||||
@@ -760,7 +762,8 @@ func (l *LegacyProvider) convert() (Providers, error) {
|
||||
}
|
||||
case "entra-id":
|
||||
provider.MicrosoftEntraIDConfig = MicrosoftEntraIDOptions{
|
||||
AllowedTenants: l.EntraIDAllowedTenants,
|
||||
AllowedTenants: l.EntraIDAllowedTenants,
|
||||
FederatedTokenAuth: l.EntraIDFederatedTokenAuth,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -166,6 +166,10 @@ type MicrosoftEntraIDOptions struct {
|
||||
// When not specified, all tenants are allowed. Redundant for single-tenant apps
|
||||
// (regular ID token validation matches the issuer).
|
||||
AllowedTenants []string `json:"allowedTenants,omitempty"`
|
||||
|
||||
// FederatedTokenAuth enable oAuth2 client authentication with federated token projected
|
||||
// by Entra Workload Identity plugin, instead of client secret.
|
||||
FederatedTokenAuth bool `json:"federatedTokenAuth,omitempty"`
|
||||
}
|
||||
|
||||
type ADFSOptions struct {
|
||||
|
||||
+59
-12
@@ -46,20 +46,47 @@ func validateProvider(provider options.Provider, providerIDs map[string]struct{}
|
||||
msgs = append(msgs, "provider missing setting: client-id")
|
||||
}
|
||||
|
||||
// login.gov uses a signed JWT to authenticate, not a client-secret
|
||||
if provider.Type != "login.gov" {
|
||||
if provider.ClientSecret == "" && provider.ClientSecretFile == "" {
|
||||
msgs = append(msgs, "missing setting: client-secret or client-secret-file")
|
||||
}
|
||||
if provider.ClientSecret == "" && provider.ClientSecretFile != "" {
|
||||
_, err := os.ReadFile(provider.ClientSecretFile)
|
||||
if err != nil {
|
||||
msgs = append(msgs, "could not read client secret file: "+provider.ClientSecretFile)
|
||||
}
|
||||
}
|
||||
if providerRequiresClientSecret(provider) {
|
||||
msgs = append(msgs, validateClientSecret(provider)...)
|
||||
}
|
||||
|
||||
msgs = append(msgs, validateGoogleConfig(provider)...)
|
||||
if provider.Type == "google" {
|
||||
msgs = append(msgs, validateGoogleConfig(provider)...)
|
||||
}
|
||||
|
||||
if provider.Type == "entra-id" {
|
||||
msgs = append(msgs, validateEntraConfig(provider)...)
|
||||
}
|
||||
|
||||
return msgs
|
||||
}
|
||||
|
||||
// providerRequiresClientSecret checks if provider requires client secret to be set
|
||||
// or it can be omitted in favor of JWT token to authenticate oAuth client
|
||||
func providerRequiresClientSecret(provider options.Provider) bool {
|
||||
if provider.Type == "entra-id" && provider.MicrosoftEntraIDConfig.FederatedTokenAuth {
|
||||
return false
|
||||
}
|
||||
|
||||
if provider.Type == "login.gov" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func validateClientSecret(provider options.Provider) []string {
|
||||
msgs := []string{}
|
||||
|
||||
if provider.ClientSecret == "" && provider.ClientSecretFile == "" {
|
||||
msgs = append(msgs, "missing setting: client-secret or client-secret-file")
|
||||
}
|
||||
if provider.ClientSecret == "" && provider.ClientSecretFile != "" {
|
||||
_, err := os.ReadFile(provider.ClientSecretFile)
|
||||
if err != nil {
|
||||
msgs = append(msgs, "could not read client secret file: "+provider.ClientSecretFile)
|
||||
}
|
||||
}
|
||||
|
||||
return msgs
|
||||
}
|
||||
@@ -96,3 +123,23 @@ func validateGoogleConfig(provider options.Provider) []string {
|
||||
|
||||
return msgs
|
||||
}
|
||||
|
||||
func validateEntraConfig(provider options.Provider) []string {
|
||||
msgs := []string{}
|
||||
|
||||
if provider.MicrosoftEntraIDConfig.FederatedTokenAuth {
|
||||
federatedTokenPath := os.Getenv("AZURE_FEDERATED_TOKEN_FILE")
|
||||
|
||||
if federatedTokenPath == "" {
|
||||
msgs = append(msgs, "entra federated token authentication is enabled, but AZURE_FEDERATED_TOKEN_FILE variable is not set, check your workload identity configuration.")
|
||||
return msgs
|
||||
}
|
||||
|
||||
_, err := os.ReadFile(federatedTokenPath)
|
||||
if err != nil {
|
||||
msgs = append(msgs, "could not read entra federated token file")
|
||||
}
|
||||
}
|
||||
|
||||
return msgs
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user