-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Adding OIDC auth functionality to the Azure integration #51219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
36429b9
Protobuf and configuration for Access Graph Azure Discovery
mvbrock 59c9049
Fixing rebase after protobuf gen
mvbrock f6ddddf
Updating to use existing msgraph client
mvbrock d2f2ba7
PR feedback
mvbrock 6c68433
Using variadic options
mvbrock 9788436
Removing memberOf expansion
mvbrock 3a49525
Expanding memberships by calling memberOf on each user
mvbrock 0322a83
PR feedback
mvbrock de61214
Rebase go.sum stuff
mvbrock cb6b8f5
Go mod tidy
mvbrock c9aff9f
Fixing go.mod
mvbrock f2f9634
Update lib/msgraph/paginated.go
mvbrock 856e66d
PR feedback
mvbrock d1569e3
Protobuf and configuration for Access Graph Azure Discovery
mvbrock d012d54
Adding Azure sync functionality which can be called by the Azure fetcher
mvbrock c40a317
Protobuf update
mvbrock 9c4431a
Linting
mvbrock 0a7bf93
PR feedback
mvbrock 4a32974
PR feedback
mvbrock df95f49
Updating to use existing msgraph client
mvbrock 34367b8
PR feedback
mvbrock 888fb06
Using variadic options
mvbrock 76e5f4f
Removing memberOf expansion
mvbrock 1651a36
Expanding memberships by calling memberOf on each user
mvbrock 65e7687
PR feedback
mvbrock 2697287
Rebase go.sum stuff
mvbrock c238a39
PR feedback
mvbrock faec959
Protobuf and configuration for Access Graph Azure Discovery
mvbrock a166e79
Protobuf gen fix
mvbrock a6f03f7
Rebase fixes
mvbrock 7aeab0f
More cleanup
mvbrock 1e35ed2
e ref update
mvbrock e2f6e24
Invoking token generation and returning the response
mvbrock dc9c000
Quick test with a message to make sure RPC is invoked
mvbrock 738cee6
Skeleton of new Azure OIDC RPC call
mvbrock 71ce322
Fetching the Azure OIDC token during fetcher creation and establishin…
mvbrock 5a60068
PR feedback; restricting token requests to auth, discovery, and proxy…
mvbrock dc04d94
Lint
mvbrock 7242fba
Fixing mocks
mvbrock 384ab8f
Fix imports
mvbrock 8093659
Fix test
mvbrock 770cafc
Rebase fxes
mvbrock ebcdab8
Adding back OIDC fetching, accidentally removed it during rebase
mvbrock da36e40
e ref
mvbrock 31064b0
Lint
mvbrock 696d4aa
Fix imports
mvbrock File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
395 changes: 255 additions & 140 deletions
395
api/gen/proto/go/teleport/integration/v1/integration_service.pb.go
Large diffs are not rendered by default.
Oops, something went wrong.
40 changes: 40 additions & 0 deletions
40
api/gen/proto/go/teleport/integration/v1/integration_service_grpc.pb.go
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| /* | ||
| * Teleport | ||
| * Copyright (C) 2025 Gravitational, Inc. | ||
| * | ||
| * This program is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU Affero General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU Affero General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Affero General Public License | ||
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| package integrationv1 | ||
|
|
||
| import ( | ||
| "context" | ||
|
|
||
| "github.com/gravitational/trace" | ||
|
|
||
| integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" | ||
| "github.com/gravitational/teleport/api/types" | ||
| "github.com/gravitational/teleport/lib/authz" | ||
| "github.com/gravitational/teleport/lib/integrations/azureoidc" | ||
| ) | ||
|
|
||
| // GenerateAzureOIDCToken generates a token to be used to execute an Azure OIDC Integration action. | ||
| func (s *Service) GenerateAzureOIDCToken(ctx context.Context, req *integrationpb.GenerateAzureOIDCTokenRequest) (*integrationpb.GenerateAzureOIDCTokenResponse, error) { | ||
|
mvbrock marked this conversation as resolved.
|
||
| authCtx, err := s.authorizer.Authorize(ctx) | ||
| if err != nil { | ||
| return nil, trace.Wrap(err) | ||
| } | ||
| _, err = s.cache.GetIntegration(ctx, req.Integration) | ||
| if err != nil { | ||
| return nil, trace.Wrap(err) | ||
| } | ||
| for _, allowedRole := range []types.SystemRole{types.RoleDiscovery, types.RoleAuth, types.RoleProxy} { | ||
| if authz.HasBuiltinRole(*authCtx, string(allowedRole)) { | ||
| token, err := azureoidc.GenerateEntraOIDCToken(ctx, s.cache, s.keyStoreManager, s.clock) | ||
| if err != nil { | ||
| return nil, trace.Wrap(err) | ||
| } | ||
| return &integrationpb.GenerateAzureOIDCTokenResponse{Token: token}, nil | ||
| } | ||
| } | ||
| return nil, trace.AccessDenied("token generation is only available to auth, proxy or discovery services") | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| /* | ||
| * Teleport | ||
| * Copyright (C) 2025 Gravitational, Inc. | ||
| * | ||
| * This program is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU Affero General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU Affero General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Affero General Public License | ||
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| package integrationv1 | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/gravitational/trace" | ||
| "github.com/stretchr/testify/require" | ||
|
|
||
| integrationv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" | ||
| "github.com/gravitational/teleport/api/types" | ||
| "github.com/gravitational/teleport/api/utils/keys" | ||
| "github.com/gravitational/teleport/lib/authz" | ||
| "github.com/gravitational/teleport/lib/jwt" | ||
| "github.com/gravitational/teleport/lib/tlsca" | ||
| ) | ||
|
|
||
| func TestGenerateAzureOIDCToken(t *testing.T) { | ||
| t.Parallel() | ||
| clusterName := "test-cluster" | ||
| integrationName := "my-integration" | ||
|
|
||
| publicURL := "https://example.com" | ||
|
|
||
| ca := newCertAuthority(t, types.HostCA, clusterName) | ||
| ctx, localClient, resourceSvc := initSvc(t, ca, clusterName, publicURL) | ||
|
|
||
| // Create integration | ||
| ig, err := types.NewIntegrationAzureOIDC( | ||
| types.Metadata{Name: integrationName}, | ||
| &types.AzureOIDCIntegrationSpecV1{ | ||
| TenantID: "foo", | ||
| ClientID: "bar", | ||
| }, | ||
| ) | ||
| require.NoError(t, err) | ||
| _, err = localClient.CreateIntegration(ctx, ig) | ||
| require.NoError(t, err) | ||
|
|
||
| t.Run("only Auth, Discovery, and Proxy roles should be able to generate Azure tokens", func(t *testing.T) { | ||
| // A dummy user should not be able to generate Azure OIDC tokens | ||
| ctx = authorizerForDummyUser(t, ctx, types.RoleSpecV6{ | ||
| Allow: types.RoleConditions{Rules: []types.Rule{ | ||
| {Resources: []string{types.KindIntegration}, Verbs: []string{types.VerbUse}}, | ||
| }}, | ||
| }, localClient) | ||
| _, err = resourceSvc.GenerateAzureOIDCToken(ctx, &integrationv1.GenerateAzureOIDCTokenRequest{Integration: integrationName}) | ||
| require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, got %T", err) | ||
|
|
||
| // Auth, Discovery, and Proxy roles should be able to generate Azure OIDC tokens | ||
| for _, allowedRole := range []types.SystemRole{types.RoleAuth, types.RoleDiscovery, types.RoleProxy} { | ||
| ctx = authz.ContextWithUser(ctx, authz.BuiltinRole{ | ||
| Role: types.RoleInstance, | ||
| AdditionalSystemRoles: []types.SystemRole{allowedRole}, | ||
| Username: string(allowedRole), | ||
| Identity: tlsca.Identity{ | ||
| Username: string(allowedRole), | ||
| }, | ||
| }) | ||
|
|
||
| _, err := resourceSvc.GenerateAzureOIDCToken(ctx, &integrationv1.GenerateAzureOIDCTokenRequest{Integration: integrationName}) | ||
| require.NoError(t, err) | ||
| } | ||
| }) | ||
|
|
||
| t.Run("validate the Azure token", func(t *testing.T) { | ||
| ctx = authz.ContextWithUser(ctx, authz.BuiltinRole{ | ||
| Role: types.RoleInstance, | ||
| AdditionalSystemRoles: []types.SystemRole{types.RoleDiscovery}, | ||
| Username: string(types.RoleDiscovery), | ||
| Identity: tlsca.Identity{ | ||
| Username: string(types.RoleDiscovery), | ||
| }, | ||
| }) | ||
| resp, err := resourceSvc.GenerateAzureOIDCToken(ctx, &integrationv1.GenerateAzureOIDCTokenRequest{ | ||
| Integration: integrationName, | ||
| }) | ||
| require.NoError(t, err) | ||
|
|
||
| // Validate JWT against public key | ||
| require.NotEmpty(t, ca.GetActiveKeys().JWT) | ||
| jwtPubKey := ca.GetActiveKeys().JWT[0].PublicKey | ||
| publicKey, err := keys.ParsePublicKey(jwtPubKey) | ||
| require.NoError(t, err) | ||
| key, err := jwt.New(&jwt.Config{ | ||
| ClusterName: clusterName, | ||
| Clock: resourceSvc.clock, | ||
| PublicKey: publicKey, | ||
| }) | ||
| require.NoError(t, err) | ||
|
|
||
| // Verify the Azure token using the JWT | ||
| _, err = key.VerifyAzureToken(resp.Token) | ||
| require.NoError(t, err) | ||
| }) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.