From 36429b91418cf175aff38249b24f8d119ced880b Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Tue, 17 Dec 2024 16:06:54 -0600 Subject: [PATCH 01/46] Protobuf and configuration for Access Graph Azure Discovery --- api/types/types.pb.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/api/types/types.pb.go b/api/types/types.pb.go index 7bc13fc024cf8..b0caa03d0a572 100644 --- a/api/types/types.pb.go +++ b/api/types/types.pb.go @@ -51103,6 +51103,47 @@ func (m *AccessGraphAzureSync) MarshalTo(dAtA []byte) (int, error) { return m.MarshalToSizedBuffer(dAtA[:size]) } +func (m *AccessGraphAzureSync) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Integration) > 0 { + i -= len(m.Integration) + copy(dAtA[i:], m.Integration) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Integration))) + i-- + dAtA[i] = 0x1a + } + if len(m.SubscriptionID) > 0 { + i -= len(m.SubscriptionID) + copy(dAtA[i:], m.SubscriptionID) + i = encodeVarintTypes(dAtA, i, uint64(len(m.SubscriptionID))) + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} + +func (m *AccessGraphAzureSync) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AccessGraphAzureSync) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + func (m *AccessGraphAzureSync) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i From 59c9049d0dbed02ce1d6fdcbe899b60786aa2b28 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 18 Dec 2024 15:14:34 -0600 Subject: [PATCH 02/46] Fixing rebase after protobuf gen --- api/types/types.pb.go | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/api/types/types.pb.go b/api/types/types.pb.go index b0caa03d0a572..7bc13fc024cf8 100644 --- a/api/types/types.pb.go +++ b/api/types/types.pb.go @@ -51103,47 +51103,6 @@ func (m *AccessGraphAzureSync) MarshalTo(dAtA []byte) (int, error) { return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *AccessGraphAzureSync) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.XXX_unrecognized != nil { - i -= len(m.XXX_unrecognized) - copy(dAtA[i:], m.XXX_unrecognized) - } - if len(m.Integration) > 0 { - i -= len(m.Integration) - copy(dAtA[i:], m.Integration) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Integration))) - i-- - dAtA[i] = 0x1a - } - if len(m.SubscriptionID) > 0 { - i -= len(m.SubscriptionID) - copy(dAtA[i:], m.SubscriptionID) - i = encodeVarintTypes(dAtA, i, uint64(len(m.SubscriptionID))) - i-- - dAtA[i] = 0x12 - } - return len(dAtA) - i, nil -} - -func (m *AccessGraphAzureSync) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *AccessGraphAzureSync) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - func (m *AccessGraphAzureSync) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i From f6ddddfb546d803d0e1e7f9ab8f20c237c016f35 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Thu, 19 Dec 2024 17:47:38 -0600 Subject: [PATCH 03/46] Updating to use existing msgraph client --- lib/msgraph/models.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index 3984fee85ccdf..3d44b69fe4b05 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -28,9 +28,15 @@ type GroupMember interface { isGroupMember() } +type Membership struct { + Type string `json:"@odata.type"` + ID string `json:"id"` +} + type DirectoryObject struct { - ID *string `json:"id,omitempty"` - DisplayName *string `json:"displayName,omitempty"` + ID *string `json:"id,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + MemberOf []Membership `json:"memberOf,omitempty"` } type Group struct { From d2f2ba7c773abc255442dae304086b0f5cd81979 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Fri, 20 Dec 2024 11:28:30 -0600 Subject: [PATCH 04/46] PR feedback --- lib/integrations/azureoidc/accessgraph.go | 2 +- lib/msgraph/client_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/integrations/azureoidc/accessgraph.go b/lib/integrations/azureoidc/accessgraph.go index 6cf43a41c3291..d7462f32aca58 100644 --- a/lib/integrations/azureoidc/accessgraph.go +++ b/lib/integrations/azureoidc/accessgraph.go @@ -116,7 +116,7 @@ func CreateTAGCacheFile(ctx context.Context) error { } cache := &TAGInfoCache{} - err = graphClient.IterateApplications(ctx, func(app *msgraph.Application) bool { + err = graphClient.IterateApplications(ctx, nil, func(app *msgraph.Application) bool { appID := app.AppID if appID == nil { slog.WarnContext(ctx, "app ID is nil", "app", app) diff --git a/lib/msgraph/client_test.go b/lib/msgraph/client_test.go index 174b8f924ce14..c302d91cc2f6f 100644 --- a/lib/msgraph/client_test.go +++ b/lib/msgraph/client_test.go @@ -186,7 +186,7 @@ func TestIterateUsers_Empty(t *testing.T) { baseURL: uri, pageSize: defaultPageSize, } - err = client.IterateUsers(context.Background(), func(*User) bool { + err = client.IterateUsers(context.Background(), nil, func(*User) bool { assert.Fail(t, "should never get called") return true }) @@ -215,7 +215,7 @@ func TestIterateUsers(t *testing.T) { } var users []*User - err = client.IterateUsers(context.Background(), func(u *User) bool { + err = client.IterateUsers(context.Background(), nil, func(u *User) bool { users = append(users, u) return true }) From 6c684333d39b40192c0ff9b097dd6d79f8dfc0e7 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Mon, 6 Jan 2025 13:25:30 -0600 Subject: [PATCH 05/46] Using variadic options --- lib/integrations/azureoidc/accessgraph.go | 2 +- lib/msgraph/client_test.go | 4 ++-- lib/srv/discovery/fetchers/azuresync/principals.go | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/integrations/azureoidc/accessgraph.go b/lib/integrations/azureoidc/accessgraph.go index d7462f32aca58..6cf43a41c3291 100644 --- a/lib/integrations/azureoidc/accessgraph.go +++ b/lib/integrations/azureoidc/accessgraph.go @@ -116,7 +116,7 @@ func CreateTAGCacheFile(ctx context.Context) error { } cache := &TAGInfoCache{} - err = graphClient.IterateApplications(ctx, nil, func(app *msgraph.Application) bool { + err = graphClient.IterateApplications(ctx, func(app *msgraph.Application) bool { appID := app.AppID if appID == nil { slog.WarnContext(ctx, "app ID is nil", "app", app) diff --git a/lib/msgraph/client_test.go b/lib/msgraph/client_test.go index c302d91cc2f6f..174b8f924ce14 100644 --- a/lib/msgraph/client_test.go +++ b/lib/msgraph/client_test.go @@ -186,7 +186,7 @@ func TestIterateUsers_Empty(t *testing.T) { baseURL: uri, pageSize: defaultPageSize, } - err = client.IterateUsers(context.Background(), nil, func(*User) bool { + err = client.IterateUsers(context.Background(), func(*User) bool { assert.Fail(t, "should never get called") return true }) @@ -215,7 +215,7 @@ func TestIterateUsers(t *testing.T) { } var users []*User - err = client.IterateUsers(context.Background(), nil, func(u *User) bool { + err = client.IterateUsers(context.Background(), func(u *User) bool { users = append(users, u) return true }) diff --git a/lib/srv/discovery/fetchers/azuresync/principals.go b/lib/srv/discovery/fetchers/azuresync/principals.go index 073d6c4713e0c..0f5ad35e88b16 100644 --- a/lib/srv/discovery/fetchers/azuresync/principals.go +++ b/lib/srv/discovery/fetchers/azuresync/principals.go @@ -45,7 +45,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "user"}, dirObj: user.DirectoryObject} queryResults = append(queryResults, res) return true - }) + }, msgraph.IterateWithExpandMembers()) if err != nil { return nil, trace.Wrap(err) } @@ -53,7 +53,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "group"}, dirObj: group.DirectoryObject} queryResults = append(queryResults, res) return true - }) + }, msgraph.IterateWithExpandMembers()) if err != nil { return nil, trace.Wrap(err) } @@ -61,7 +61,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "servicePrincipal"}, dirObj: servicePrincipal.DirectoryObject} queryResults = append(queryResults, res) return true - }) + }, msgraph.IterateWithExpandMembers()) if err != nil { return nil, trace.Wrap(err) } From 97884367eefe72d051e5b5a0608b8f11981cf4a1 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Mon, 6 Jan 2025 13:50:45 -0600 Subject: [PATCH 06/46] Removing memberOf expansion --- lib/msgraph/models.go | 5 ++--- lib/srv/discovery/fetchers/azuresync/principals.go | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index 3d44b69fe4b05..d0ed2e9d93c3c 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -34,9 +34,8 @@ type Membership struct { } type DirectoryObject struct { - ID *string `json:"id,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - MemberOf []Membership `json:"memberOf,omitempty"` + ID *string `json:"id,omitempty"` + DisplayName *string `json:"displayName,omitempty"` } type Group struct { diff --git a/lib/srv/discovery/fetchers/azuresync/principals.go b/lib/srv/discovery/fetchers/azuresync/principals.go index 0f5ad35e88b16..073d6c4713e0c 100644 --- a/lib/srv/discovery/fetchers/azuresync/principals.go +++ b/lib/srv/discovery/fetchers/azuresync/principals.go @@ -45,7 +45,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "user"}, dirObj: user.DirectoryObject} queryResults = append(queryResults, res) return true - }, msgraph.IterateWithExpandMembers()) + }) if err != nil { return nil, trace.Wrap(err) } @@ -53,7 +53,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "group"}, dirObj: group.DirectoryObject} queryResults = append(queryResults, res) return true - }, msgraph.IterateWithExpandMembers()) + }) if err != nil { return nil, trace.Wrap(err) } @@ -61,7 +61,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "servicePrincipal"}, dirObj: servicePrincipal.DirectoryObject} queryResults = append(queryResults, res) return true - }, msgraph.IterateWithExpandMembers()) + }) if err != nil { return nil, trace.Wrap(err) } From 3a49525202ede709386add09b6ed92252f6b17b1 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Mon, 6 Jan 2025 23:15:04 -0600 Subject: [PATCH 07/46] Expanding memberships by calling memberOf on each user --- lib/msgraph/models.go | 9 +++++++++ lib/msgraph/paginated.go | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index d0ed2e9d93c3c..b76c4904ad3e9 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -190,3 +190,12 @@ func decodeGroupMember(msg json.RawMessage) (GroupMember, error) { return member, trace.Wrap(err) } + +func decodeDirectoryObject(msg json.RawMessage) (*DirectoryObject, error) { + var d *DirectoryObject + err := json.Unmarshal(msg, &d) + if err != nil { + return nil, trace.Wrap(err) + } + return d, nil +} diff --git a/lib/msgraph/paginated.go b/lib/msgraph/paginated.go index a0b9488af9d70..1e6a915fbe634 100644 --- a/lib/msgraph/paginated.go +++ b/lib/msgraph/paginated.go @@ -109,6 +109,29 @@ func (c *Client) IterateServicePrincipals(ctx context.Context, f func(principal return iterateSimple(c, ctx, "servicePrincipals", f) } +func (c *Client) IterateUserMembership(ctx context.Context, userID string, f func(obj *DirectoryObject) bool) error { + var err error + itErr := c.iterate(ctx, path.Join("users", userID, "memberOf"), func(msg json.RawMessage) bool { + var page []json.RawMessage + if err = json.Unmarshal(msg, &page); err != nil { + return false + } + for _, entry := range page { + var d *DirectoryObject + err := json.Unmarshal(entry, &d) + if err != nil { + return false + } + f(d) + } + return true + }) + if err != nil { + return trace.Wrap(err) + } + return trace.Wrap(itErr) +} + // IterateGroupMembers lists all members for the given Entra ID group using pagination. // `f` will be called for each object in the result set. // if `f` returns `false`, the iteration is stopped (equivalent to `break` in a normal loop). From 0322a83da732f09404e8b849c6cd1cfb9c9c3984 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 8 Jan 2025 22:30:19 -0600 Subject: [PATCH 08/46] PR feedback --- lib/msgraph/models.go | 9 --------- lib/msgraph/paginated.go | 27 ++++++--------------------- 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index b76c4904ad3e9..d0ed2e9d93c3c 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -190,12 +190,3 @@ func decodeGroupMember(msg json.RawMessage) (GroupMember, error) { return member, trace.Wrap(err) } - -func decodeDirectoryObject(msg json.RawMessage) (*DirectoryObject, error) { - var d *DirectoryObject - err := json.Unmarshal(msg, &d) - if err != nil { - return nil, trace.Wrap(err) - } - return d, nil -} diff --git a/lib/msgraph/paginated.go b/lib/msgraph/paginated.go index 1e6a915fbe634..da44a4f442a1b 100644 --- a/lib/msgraph/paginated.go +++ b/lib/msgraph/paginated.go @@ -109,27 +109,12 @@ func (c *Client) IterateServicePrincipals(ctx context.Context, f func(principal return iterateSimple(c, ctx, "servicePrincipals", f) } -func (c *Client) IterateUserMembership(ctx context.Context, userID string, f func(obj *DirectoryObject) bool) error { - var err error - itErr := c.iterate(ctx, path.Join("users", userID, "memberOf"), func(msg json.RawMessage) bool { - var page []json.RawMessage - if err = json.Unmarshal(msg, &page); err != nil { - return false - } - for _, entry := range page { - var d *DirectoryObject - err := json.Unmarshal(entry, &d) - if err != nil { - return false - } - f(d) - } - return true - }) - if err != nil { - return trace.Wrap(err) - } - return trace.Wrap(itErr) +// IterateUserMembership lists all group memberships for a given user ID as directory objects. +// `f` will be called for each directory object in the result set. +// if `f` returns `false`, the iteration is stopped (equivalent to `break` in a normal loop). +// Ref: [https://learn.microsoft.com/en-us/graph/api/group-list-memberof]. +func (c *Client) IterateUserMembership(ctx context.Context, userID string, f func(object *DirectoryObject) bool) error { + return iterateSimple(c, ctx, path.Join("users", userID, "memberOf"), f) } // IterateGroupMembers lists all members for the given Entra ID group using pagination. From de612145cce82d863091ef00d953187a4dcd9655 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 8 Jan 2025 22:40:43 -0600 Subject: [PATCH 09/46] Rebase go.sum stuff --- go.mod | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2269979efef2e..4c22de4694f3d 100644 --- a/go.mod +++ b/go.mod @@ -245,6 +245,8 @@ require ( software.sslmate.com/src/go-pkcs12 v0.5.0 ) +require github.com/xanzy/go-gitlab v0.115.0 + require ( cel.dev/expr v0.19.1 // indirect cloud.google.com/go v0.117.0 // indirect @@ -522,7 +524,6 @@ require ( github.com/vbatts/tar-split v0.11.5 // indirect github.com/weppos/publicsuffix-go v0.30.3-0.20240510084413-5f1d03393b3d // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xanzy/go-gitlab v0.115.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect From cb6b8f5dff910ef4975900f62bb2215edab8a47b Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 8 Jan 2025 22:47:34 -0600 Subject: [PATCH 10/46] Go mod tidy --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4c22de4694f3d..6ab986f46c43d 100644 --- a/go.mod +++ b/go.mod @@ -245,7 +245,7 @@ require ( software.sslmate.com/src/go-pkcs12 v0.5.0 ) -require github.com/xanzy/go-gitlab v0.115.0 +require github.com/xanzy/go-gitlab v0.115.0 // indirect require ( cel.dev/expr v0.19.1 // indirect From c9aff9f5f2ec9201030f4128b368552678cb1cd7 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Thu, 9 Jan 2025 10:36:27 -0600 Subject: [PATCH 11/46] Fixing go.mod --- go.mod | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 6ab986f46c43d..2269979efef2e 100644 --- a/go.mod +++ b/go.mod @@ -245,8 +245,6 @@ require ( software.sslmate.com/src/go-pkcs12 v0.5.0 ) -require github.com/xanzy/go-gitlab v0.115.0 // indirect - require ( cel.dev/expr v0.19.1 // indirect cloud.google.com/go v0.117.0 // indirect @@ -524,6 +522,7 @@ require ( github.com/vbatts/tar-split v0.11.5 // indirect github.com/weppos/publicsuffix-go v0.30.3-0.20240510084413-5f1d03393b3d // indirect github.com/x448/float16 v0.8.4 // indirect + github.com/xanzy/go-gitlab v0.115.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect From f2f96347b16d4ae4b0c1f279c8eb6e20cbba0f39 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Fri, 10 Jan 2025 10:00:39 -0600 Subject: [PATCH 12/46] Update lib/msgraph/paginated.go Co-authored-by: Tiago Silva --- lib/msgraph/paginated.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msgraph/paginated.go b/lib/msgraph/paginated.go index da44a4f442a1b..0321b8a326d9c 100644 --- a/lib/msgraph/paginated.go +++ b/lib/msgraph/paginated.go @@ -109,11 +109,11 @@ func (c *Client) IterateServicePrincipals(ctx context.Context, f func(principal return iterateSimple(c, ctx, "servicePrincipals", f) } -// IterateUserMembership lists all group memberships for a given user ID as directory objects. +// IterateUserMemberships lists all group memberships for a given user ID as directory objects. // `f` will be called for each directory object in the result set. // if `f` returns `false`, the iteration is stopped (equivalent to `break` in a normal loop). // Ref: [https://learn.microsoft.com/en-us/graph/api/group-list-memberof]. -func (c *Client) IterateUserMembership(ctx context.Context, userID string, f func(object *DirectoryObject) bool) error { +func (c *Client) IterateUserMemberships(ctx context.Context, userID string, f func(object *DirectoryObject) bool) error { return iterateSimple(c, ctx, path.Join("users", userID, "memberOf"), f) } From 856e66d10bed5f951a225c97bd2fc61053e93d22 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Fri, 10 Jan 2025 10:11:21 -0600 Subject: [PATCH 13/46] PR feedback --- lib/msgraph/models.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index d0ed2e9d93c3c..3984fee85ccdf 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -28,11 +28,6 @@ type GroupMember interface { isGroupMember() } -type Membership struct { - Type string `json:"@odata.type"` - ID string `json:"id"` -} - type DirectoryObject struct { ID *string `json:"id,omitempty"` DisplayName *string `json:"displayName,omitempty"` From d1569e345940d1240fc817628dda24f304dfd90a Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Tue, 17 Dec 2024 16:06:54 -0600 Subject: [PATCH 14/46] Protobuf and configuration for Access Graph Azure Discovery --- api/types/types.pb.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/api/types/types.pb.go b/api/types/types.pb.go index 7bc13fc024cf8..3cace5cb4f5ec 100644 --- a/api/types/types.pb.go +++ b/api/types/types.pb.go @@ -135653,6 +135653,40 @@ func (m *AccessGraphSync) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Azure", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Azure = append(m.Azure, &AccessGraphAzureSync{}) + if err := m.Azure[len(m.Azure)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) From d012d54f70069766374d0fbb63166978713639df Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Tue, 17 Dec 2024 17:18:58 -0600 Subject: [PATCH 15/46] Adding Azure sync functionality which can be called by the Azure fetcher --- lib/srv/discovery/common/reconcile.go | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 lib/srv/discovery/common/reconcile.go diff --git a/lib/srv/discovery/common/reconcile.go b/lib/srv/discovery/common/reconcile.go new file mode 100644 index 0000000000000..9161ae69b95b1 --- /dev/null +++ b/lib/srv/discovery/common/reconcile.go @@ -0,0 +1,32 @@ +/* + * Teleport + * Copyright (C) 2024 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 . + */ + +package common + +func DeduplicateSlice[T any](s []T, key func(T) string) []T { + out := make([]T, 0, len(s)) + seen := make(map[string]struct{}) + for _, v := range s { + if _, ok := seen[key(v)]; ok { + continue + } + seen[key(v)] = struct{}{} + out = append(out, v) + } + return out +} From c40a317961e6161a6f9af179953194fc961edad1 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 18 Dec 2024 15:25:19 -0600 Subject: [PATCH 16/46] Protobuf update --- api/types/types.pb.go | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/api/types/types.pb.go b/api/types/types.pb.go index 3cace5cb4f5ec..7bc13fc024cf8 100644 --- a/api/types/types.pb.go +++ b/api/types/types.pb.go @@ -135653,40 +135653,6 @@ func (m *AccessGraphSync) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Azure", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Azure = append(m.Azure, &AccessGraphAzureSync{}) - if err := m.Azure[len(m.Azure)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) From 9c4431a5821fe6dfc2729bbde487bd875007242b Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Mon, 13 Jan 2025 14:44:41 -0600 Subject: [PATCH 17/46] Linting --- lib/msgraph/paginated.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/msgraph/paginated.go b/lib/msgraph/paginated.go index 0321b8a326d9c..a0b9488af9d70 100644 --- a/lib/msgraph/paginated.go +++ b/lib/msgraph/paginated.go @@ -109,14 +109,6 @@ func (c *Client) IterateServicePrincipals(ctx context.Context, f func(principal return iterateSimple(c, ctx, "servicePrincipals", f) } -// IterateUserMemberships lists all group memberships for a given user ID as directory objects. -// `f` will be called for each directory object in the result set. -// if `f` returns `false`, the iteration is stopped (equivalent to `break` in a normal loop). -// Ref: [https://learn.microsoft.com/en-us/graph/api/group-list-memberof]. -func (c *Client) IterateUserMemberships(ctx context.Context, userID string, f func(object *DirectoryObject) bool) error { - return iterateSimple(c, ctx, path.Join("users", userID, "memberOf"), f) -} - // IterateGroupMembers lists all members for the given Entra ID group using pagination. // `f` will be called for each object in the result set. // if `f` returns `false`, the iteration is stopped (equivalent to `break` in a normal loop). From 0a7bf93285c0cec62adf8656901211bc16a7c2a4 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 15 Jan 2025 14:47:07 -0600 Subject: [PATCH 18/46] PR feedback --- lib/srv/discovery/common/reconcile.go | 32 --------------------------- lib/utils/slice.go | 13 +++++++++++ 2 files changed, 13 insertions(+), 32 deletions(-) delete mode 100644 lib/srv/discovery/common/reconcile.go diff --git a/lib/srv/discovery/common/reconcile.go b/lib/srv/discovery/common/reconcile.go deleted file mode 100644 index 9161ae69b95b1..0000000000000 --- a/lib/srv/discovery/common/reconcile.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Teleport - * Copyright (C) 2024 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 . - */ - -package common - -func DeduplicateSlice[T any](s []T, key func(T) string) []T { - out := make([]T, 0, len(s)) - seen := make(map[string]struct{}) - for _, v := range s { - if _, ok := seen[key(v)]; ok { - continue - } - seen[key(v)] = struct{}{} - out = append(out, v) - } - return out -} diff --git a/lib/utils/slice.go b/lib/utils/slice.go index 4009277ceef50..8cabb489d037c 100644 --- a/lib/utils/slice.go +++ b/lib/utils/slice.go @@ -142,3 +142,16 @@ func FromSlice[T any](r []T, key func(T) string) map[string]T { return out } + +func DeduplicateSlice[T any](s []T, key func(T) string) []T { + out := make([]T, 0, len(s)) + seen := make(map[string]struct{}) + for _, v := range s { + if _, ok := seen[key(v)]; ok { + continue + } + seen[key(v)] = struct{}{} + out = append(out, v) + } + return out +} From 4a3297403c930f6f80e40e63a5c00b5b375de547 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Thu, 16 Jan 2025 17:05:25 -0600 Subject: [PATCH 19/46] PR feedback --- lib/utils/slice.go | 3 +- lib/utils/slice_test.go | 90 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/lib/utils/slice.go b/lib/utils/slice.go index 8cabb489d037c..8b4f73b9543d5 100644 --- a/lib/utils/slice.go +++ b/lib/utils/slice.go @@ -143,7 +143,8 @@ func FromSlice[T any](r []T, key func(T) string) map[string]T { return out } -func DeduplicateSlice[T any](s []T, key func(T) string) []T { +// DeduplicateKey returns a deduplicated slice by comparing key values from the key function +func DeduplicateKey[T any](s []T, key func(T) string) []T { out := make([]T, 0, len(s)) seen := make(map[string]struct{}) for _, v := range s { diff --git a/lib/utils/slice_test.go b/lib/utils/slice_test.go index 76f4a1dd1a29d..fce1f113025d1 100644 --- a/lib/utils/slice_test.go +++ b/lib/utils/slice_test.go @@ -19,6 +19,7 @@ package utils import ( + "fmt" "testing" "github.com/stretchr/testify/require" @@ -41,3 +42,92 @@ func TestSlice(t *testing.T) { pool.Put(slice) } } + +// TestDuplicateKey tests slice deduplication via key function +func TestDeduplicateKey(t *testing.T) { + t.Parallel() + + stringTests := []struct { + name string + slice []string + keyFn func(string) string + expected []string + }{ + { + name: "EmptyStringSlice", + slice: []string{}, + keyFn: func(s string) string { return s }, + expected: []string{}, + }, + { + name: "NoStringDuplicates", + slice: []string{"foo", "bar", "baz"}, + keyFn: func(s string) string { return s }, + expected: []string{"foo", "bar", "baz"}, + }, + { + name: "StringDuplicates", + slice: []string{"foo", "bar", "bar", "bar", "baz", "baz"}, + keyFn: func(s string) string { return s }, + expected: []string{"foo", "bar", "baz"}, + }, + { + name: "StringDuplicatesWeirdKeyFn", + slice: []string{"foo", "bar", "bar", "bar", "baz", "baz"}, + keyFn: func(s string) string { return "huh" }, + expected: []string{"foo"}, + }, + } + for _, tt := range stringTests { + t.Run(tt.name, func(t *testing.T) { + res := DeduplicateKey(tt.slice, tt.keyFn) + require.Equal(t, tt.expected, res) + }) + } + + type dedupeStruct struct { + a string + b int + c bool + } + dedupeStructKeyFn := func(d dedupeStruct) string { return fmt.Sprintf("%s:%d:%v", d.a, d.b, d.c) } + structTests := []struct { + name string + slice []dedupeStruct + keyFn func(d dedupeStruct) string + expected []dedupeStruct + }{ + { + name: "EmptySlice", + slice: []dedupeStruct{}, + keyFn: dedupeStructKeyFn, + expected: []dedupeStruct{}, + }, + { + name: "NoStructDuplicates", + slice: []dedupeStruct{ + {a: "foo", b: 1, c: true}, + {a: "foo", b: 1, c: false}, + {a: "foo", b: 2, c: true}, + {a: "bar", b: 1, c: true}, + {a: "bar", b: 1, c: false}, + {a: "bar", b: 2, c: true}, + }, + keyFn: dedupeStructKeyFn, + expected: []dedupeStruct{ + {a: "foo", b: 1, c: true}, + {a: "foo", b: 1, c: false}, + {a: "foo", b: 2, c: true}, + {a: "bar", b: 1, c: true}, + {a: "bar", b: 1, c: false}, + {a: "bar", b: 2, c: true}, + }, + }, + } + for _, tt := range structTests { + t.Run(tt.name, func(t *testing.T) { + res := DeduplicateKey(tt.slice, tt.keyFn) + require.Equal(t, tt.expected, res) + }) + } +} From df95f49422f13825f3a8f29baccb0799582cd979 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Thu, 19 Dec 2024 17:47:38 -0600 Subject: [PATCH 20/46] Updating to use existing msgraph client --- lib/msgraph/models.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index 3984fee85ccdf..3d44b69fe4b05 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -28,9 +28,15 @@ type GroupMember interface { isGroupMember() } +type Membership struct { + Type string `json:"@odata.type"` + ID string `json:"id"` +} + type DirectoryObject struct { - ID *string `json:"id,omitempty"` - DisplayName *string `json:"displayName,omitempty"` + ID *string `json:"id,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + MemberOf []Membership `json:"memberOf,omitempty"` } type Group struct { From 34367b81ac950a54a1df9b0a72cd54952720c1cd Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Fri, 20 Dec 2024 11:28:30 -0600 Subject: [PATCH 21/46] PR feedback --- lib/integrations/azureoidc/accessgraph.go | 2 +- lib/msgraph/client_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/integrations/azureoidc/accessgraph.go b/lib/integrations/azureoidc/accessgraph.go index 6cf43a41c3291..d7462f32aca58 100644 --- a/lib/integrations/azureoidc/accessgraph.go +++ b/lib/integrations/azureoidc/accessgraph.go @@ -116,7 +116,7 @@ func CreateTAGCacheFile(ctx context.Context) error { } cache := &TAGInfoCache{} - err = graphClient.IterateApplications(ctx, func(app *msgraph.Application) bool { + err = graphClient.IterateApplications(ctx, nil, func(app *msgraph.Application) bool { appID := app.AppID if appID == nil { slog.WarnContext(ctx, "app ID is nil", "app", app) diff --git a/lib/msgraph/client_test.go b/lib/msgraph/client_test.go index 174b8f924ce14..c302d91cc2f6f 100644 --- a/lib/msgraph/client_test.go +++ b/lib/msgraph/client_test.go @@ -186,7 +186,7 @@ func TestIterateUsers_Empty(t *testing.T) { baseURL: uri, pageSize: defaultPageSize, } - err = client.IterateUsers(context.Background(), func(*User) bool { + err = client.IterateUsers(context.Background(), nil, func(*User) bool { assert.Fail(t, "should never get called") return true }) @@ -215,7 +215,7 @@ func TestIterateUsers(t *testing.T) { } var users []*User - err = client.IterateUsers(context.Background(), func(u *User) bool { + err = client.IterateUsers(context.Background(), nil, func(u *User) bool { users = append(users, u) return true }) From 888fb0602717cfabad9499afaa3a70bf73dee99e Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Mon, 6 Jan 2025 13:25:30 -0600 Subject: [PATCH 22/46] Using variadic options --- lib/integrations/azureoidc/accessgraph.go | 2 +- lib/msgraph/client_test.go | 4 ++-- lib/srv/discovery/fetchers/azuresync/principals.go | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/integrations/azureoidc/accessgraph.go b/lib/integrations/azureoidc/accessgraph.go index d7462f32aca58..6cf43a41c3291 100644 --- a/lib/integrations/azureoidc/accessgraph.go +++ b/lib/integrations/azureoidc/accessgraph.go @@ -116,7 +116,7 @@ func CreateTAGCacheFile(ctx context.Context) error { } cache := &TAGInfoCache{} - err = graphClient.IterateApplications(ctx, nil, func(app *msgraph.Application) bool { + err = graphClient.IterateApplications(ctx, func(app *msgraph.Application) bool { appID := app.AppID if appID == nil { slog.WarnContext(ctx, "app ID is nil", "app", app) diff --git a/lib/msgraph/client_test.go b/lib/msgraph/client_test.go index c302d91cc2f6f..174b8f924ce14 100644 --- a/lib/msgraph/client_test.go +++ b/lib/msgraph/client_test.go @@ -186,7 +186,7 @@ func TestIterateUsers_Empty(t *testing.T) { baseURL: uri, pageSize: defaultPageSize, } - err = client.IterateUsers(context.Background(), nil, func(*User) bool { + err = client.IterateUsers(context.Background(), func(*User) bool { assert.Fail(t, "should never get called") return true }) @@ -215,7 +215,7 @@ func TestIterateUsers(t *testing.T) { } var users []*User - err = client.IterateUsers(context.Background(), nil, func(u *User) bool { + err = client.IterateUsers(context.Background(), func(u *User) bool { users = append(users, u) return true }) diff --git a/lib/srv/discovery/fetchers/azuresync/principals.go b/lib/srv/discovery/fetchers/azuresync/principals.go index 073d6c4713e0c..0f5ad35e88b16 100644 --- a/lib/srv/discovery/fetchers/azuresync/principals.go +++ b/lib/srv/discovery/fetchers/azuresync/principals.go @@ -45,7 +45,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "user"}, dirObj: user.DirectoryObject} queryResults = append(queryResults, res) return true - }) + }, msgraph.IterateWithExpandMembers()) if err != nil { return nil, trace.Wrap(err) } @@ -53,7 +53,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "group"}, dirObj: group.DirectoryObject} queryResults = append(queryResults, res) return true - }) + }, msgraph.IterateWithExpandMembers()) if err != nil { return nil, trace.Wrap(err) } @@ -61,7 +61,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "servicePrincipal"}, dirObj: servicePrincipal.DirectoryObject} queryResults = append(queryResults, res) return true - }) + }, msgraph.IterateWithExpandMembers()) if err != nil { return nil, trace.Wrap(err) } From 76e5f4ff848ca871f85e1bb2eb31ef58f083ce75 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Mon, 6 Jan 2025 13:50:45 -0600 Subject: [PATCH 23/46] Removing memberOf expansion --- lib/msgraph/models.go | 5 ++--- lib/srv/discovery/fetchers/azuresync/principals.go | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index 3d44b69fe4b05..d0ed2e9d93c3c 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -34,9 +34,8 @@ type Membership struct { } type DirectoryObject struct { - ID *string `json:"id,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - MemberOf []Membership `json:"memberOf,omitempty"` + ID *string `json:"id,omitempty"` + DisplayName *string `json:"displayName,omitempty"` } type Group struct { diff --git a/lib/srv/discovery/fetchers/azuresync/principals.go b/lib/srv/discovery/fetchers/azuresync/principals.go index 0f5ad35e88b16..073d6c4713e0c 100644 --- a/lib/srv/discovery/fetchers/azuresync/principals.go +++ b/lib/srv/discovery/fetchers/azuresync/principals.go @@ -45,7 +45,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "user"}, dirObj: user.DirectoryObject} queryResults = append(queryResults, res) return true - }, msgraph.IterateWithExpandMembers()) + }) if err != nil { return nil, trace.Wrap(err) } @@ -53,7 +53,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "group"}, dirObj: group.DirectoryObject} queryResults = append(queryResults, res) return true - }, msgraph.IterateWithExpandMembers()) + }) if err != nil { return nil, trace.Wrap(err) } @@ -61,7 +61,7 @@ func fetchPrincipals(ctx context.Context, subscriptionID string, cli *msgraph.Cl res := queryResult{metadata: dirObjMetadata{objectType: "servicePrincipal"}, dirObj: servicePrincipal.DirectoryObject} queryResults = append(queryResults, res) return true - }, msgraph.IterateWithExpandMembers()) + }) if err != nil { return nil, trace.Wrap(err) } From 1651a36163d9a66ea2a68e1cbedfc9bb0ed64190 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Mon, 6 Jan 2025 23:15:04 -0600 Subject: [PATCH 24/46] Expanding memberships by calling memberOf on each user --- lib/msgraph/models.go | 9 +++++++++ lib/msgraph/paginated.go | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index d0ed2e9d93c3c..b76c4904ad3e9 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -190,3 +190,12 @@ func decodeGroupMember(msg json.RawMessage) (GroupMember, error) { return member, trace.Wrap(err) } + +func decodeDirectoryObject(msg json.RawMessage) (*DirectoryObject, error) { + var d *DirectoryObject + err := json.Unmarshal(msg, &d) + if err != nil { + return nil, trace.Wrap(err) + } + return d, nil +} diff --git a/lib/msgraph/paginated.go b/lib/msgraph/paginated.go index a0b9488af9d70..1e6a915fbe634 100644 --- a/lib/msgraph/paginated.go +++ b/lib/msgraph/paginated.go @@ -109,6 +109,29 @@ func (c *Client) IterateServicePrincipals(ctx context.Context, f func(principal return iterateSimple(c, ctx, "servicePrincipals", f) } +func (c *Client) IterateUserMembership(ctx context.Context, userID string, f func(obj *DirectoryObject) bool) error { + var err error + itErr := c.iterate(ctx, path.Join("users", userID, "memberOf"), func(msg json.RawMessage) bool { + var page []json.RawMessage + if err = json.Unmarshal(msg, &page); err != nil { + return false + } + for _, entry := range page { + var d *DirectoryObject + err := json.Unmarshal(entry, &d) + if err != nil { + return false + } + f(d) + } + return true + }) + if err != nil { + return trace.Wrap(err) + } + return trace.Wrap(itErr) +} + // IterateGroupMembers lists all members for the given Entra ID group using pagination. // `f` will be called for each object in the result set. // if `f` returns `false`, the iteration is stopped (equivalent to `break` in a normal loop). From 65e76877c5108b813a6ab7b3391da1a3bc435afc Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 8 Jan 2025 22:30:19 -0600 Subject: [PATCH 25/46] PR feedback --- lib/msgraph/models.go | 9 --------- lib/msgraph/paginated.go | 27 ++++++--------------------- 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index b76c4904ad3e9..d0ed2e9d93c3c 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -190,12 +190,3 @@ func decodeGroupMember(msg json.RawMessage) (GroupMember, error) { return member, trace.Wrap(err) } - -func decodeDirectoryObject(msg json.RawMessage) (*DirectoryObject, error) { - var d *DirectoryObject - err := json.Unmarshal(msg, &d) - if err != nil { - return nil, trace.Wrap(err) - } - return d, nil -} diff --git a/lib/msgraph/paginated.go b/lib/msgraph/paginated.go index 1e6a915fbe634..da44a4f442a1b 100644 --- a/lib/msgraph/paginated.go +++ b/lib/msgraph/paginated.go @@ -109,27 +109,12 @@ func (c *Client) IterateServicePrincipals(ctx context.Context, f func(principal return iterateSimple(c, ctx, "servicePrincipals", f) } -func (c *Client) IterateUserMembership(ctx context.Context, userID string, f func(obj *DirectoryObject) bool) error { - var err error - itErr := c.iterate(ctx, path.Join("users", userID, "memberOf"), func(msg json.RawMessage) bool { - var page []json.RawMessage - if err = json.Unmarshal(msg, &page); err != nil { - return false - } - for _, entry := range page { - var d *DirectoryObject - err := json.Unmarshal(entry, &d) - if err != nil { - return false - } - f(d) - } - return true - }) - if err != nil { - return trace.Wrap(err) - } - return trace.Wrap(itErr) +// IterateUserMembership lists all group memberships for a given user ID as directory objects. +// `f` will be called for each directory object in the result set. +// if `f` returns `false`, the iteration is stopped (equivalent to `break` in a normal loop). +// Ref: [https://learn.microsoft.com/en-us/graph/api/group-list-memberof]. +func (c *Client) IterateUserMembership(ctx context.Context, userID string, f func(object *DirectoryObject) bool) error { + return iterateSimple(c, ctx, path.Join("users", userID, "memberOf"), f) } // IterateGroupMembers lists all members for the given Entra ID group using pagination. From 269728785db807a0b4d23a7f0e1a0ece6d30fa06 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 8 Jan 2025 22:40:43 -0600 Subject: [PATCH 26/46] Rebase go.sum stuff --- go.mod | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2269979efef2e..4c22de4694f3d 100644 --- a/go.mod +++ b/go.mod @@ -245,6 +245,8 @@ require ( software.sslmate.com/src/go-pkcs12 v0.5.0 ) +require github.com/xanzy/go-gitlab v0.115.0 + require ( cel.dev/expr v0.19.1 // indirect cloud.google.com/go v0.117.0 // indirect @@ -522,7 +524,6 @@ require ( github.com/vbatts/tar-split v0.11.5 // indirect github.com/weppos/publicsuffix-go v0.30.3-0.20240510084413-5f1d03393b3d // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xanzy/go-gitlab v0.115.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect From c238a398a975c602266e5284e851781d46eaabee Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Fri, 10 Jan 2025 10:11:21 -0600 Subject: [PATCH 27/46] PR feedback --- lib/msgraph/models.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/msgraph/models.go b/lib/msgraph/models.go index d0ed2e9d93c3c..3984fee85ccdf 100644 --- a/lib/msgraph/models.go +++ b/lib/msgraph/models.go @@ -28,11 +28,6 @@ type GroupMember interface { isGroupMember() } -type Membership struct { - Type string `json:"@odata.type"` - ID string `json:"id"` -} - type DirectoryObject struct { ID *string `json:"id,omitempty"` DisplayName *string `json:"displayName,omitempty"` From faec959cde957c21991271fb8ba4d143c5724dde Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Tue, 17 Dec 2024 16:06:54 -0600 Subject: [PATCH 28/46] Protobuf and configuration for Access Graph Azure Discovery --- api/types/types.pb.go | 61 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/api/types/types.pb.go b/api/types/types.pb.go index 7bc13fc024cf8..8556c0d2d58df 100644 --- a/api/types/types.pb.go +++ b/api/types/types.pb.go @@ -51129,6 +51129,47 @@ func (m *AccessGraphAzureSync) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *AccessGraphAzureSync) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AccessGraphAzureSync) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AccessGraphAzureSync) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Integration) > 0 { + i -= len(m.Integration) + copy(dAtA[i:], m.Integration) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Integration))) + i-- + dAtA[i] = 0x1a + } + if len(m.SubscriptionID) > 0 { + i -= len(m.SubscriptionID) + copy(dAtA[i:], m.SubscriptionID) + i = encodeVarintTypes(dAtA, i, uint64(len(m.SubscriptionID))) + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} + func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { offset -= sovTypes(v) base := offset @@ -62659,6 +62700,26 @@ func (m *AccessGraphAzureSync) Size() (n int) { return n } +func (m *AccessGraphAzureSync) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.SubscriptionID) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Integration) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func sovTypes(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } From a166e79297f74eb0829e2fff4a80f23563f0eeb4 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 18 Dec 2024 15:26:31 -0600 Subject: [PATCH 29/46] Protobuf gen fix --- api/types/types.pb.go | 61 ------------------------------------------- 1 file changed, 61 deletions(-) diff --git a/api/types/types.pb.go b/api/types/types.pb.go index 8556c0d2d58df..7bc13fc024cf8 100644 --- a/api/types/types.pb.go +++ b/api/types/types.pb.go @@ -51129,47 +51129,6 @@ func (m *AccessGraphAzureSync) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *AccessGraphAzureSync) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *AccessGraphAzureSync) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *AccessGraphAzureSync) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.XXX_unrecognized != nil { - i -= len(m.XXX_unrecognized) - copy(dAtA[i:], m.XXX_unrecognized) - } - if len(m.Integration) > 0 { - i -= len(m.Integration) - copy(dAtA[i:], m.Integration) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Integration))) - i-- - dAtA[i] = 0x1a - } - if len(m.SubscriptionID) > 0 { - i -= len(m.SubscriptionID) - copy(dAtA[i:], m.SubscriptionID) - i = encodeVarintTypes(dAtA, i, uint64(len(m.SubscriptionID))) - i-- - dAtA[i] = 0x12 - } - return len(dAtA) - i, nil -} - func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { offset -= sovTypes(v) base := offset @@ -62700,26 +62659,6 @@ func (m *AccessGraphAzureSync) Size() (n int) { return n } -func (m *AccessGraphAzureSync) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.SubscriptionID) - if l > 0 { - n += 1 + l + sovTypes(uint64(l)) - } - l = len(m.Integration) - if l > 0 { - n += 1 + l + sovTypes(uint64(l)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - func sovTypes(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } From a6f03f73e532f7855ea2e5af69286dd66126da0a Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 22 Jan 2025 15:48:06 -0600 Subject: [PATCH 30/46] Rebase fixes --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4c22de4694f3d..6ab986f46c43d 100644 --- a/go.mod +++ b/go.mod @@ -245,7 +245,7 @@ require ( software.sslmate.com/src/go-pkcs12 v0.5.0 ) -require github.com/xanzy/go-gitlab v0.115.0 +require github.com/xanzy/go-gitlab v0.115.0 // indirect require ( cel.dev/expr v0.19.1 // indirect From 7aeab0f99f63e6f3b211a687759a7e5311efcc3f Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 22 Jan 2025 16:21:31 -0600 Subject: [PATCH 31/46] More cleanup --- go.mod | 3 +- lib/msgraph/paginated.go | 8 ---- lib/utils/slice.go | 14 ------- lib/utils/slice_test.go | 90 ---------------------------------------- 4 files changed, 1 insertion(+), 114 deletions(-) diff --git a/go.mod b/go.mod index 6ab986f46c43d..2269979efef2e 100644 --- a/go.mod +++ b/go.mod @@ -245,8 +245,6 @@ require ( software.sslmate.com/src/go-pkcs12 v0.5.0 ) -require github.com/xanzy/go-gitlab v0.115.0 // indirect - require ( cel.dev/expr v0.19.1 // indirect cloud.google.com/go v0.117.0 // indirect @@ -524,6 +522,7 @@ require ( github.com/vbatts/tar-split v0.11.5 // indirect github.com/weppos/publicsuffix-go v0.30.3-0.20240510084413-5f1d03393b3d // indirect github.com/x448/float16 v0.8.4 // indirect + github.com/xanzy/go-gitlab v0.115.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect diff --git a/lib/msgraph/paginated.go b/lib/msgraph/paginated.go index da44a4f442a1b..a0b9488af9d70 100644 --- a/lib/msgraph/paginated.go +++ b/lib/msgraph/paginated.go @@ -109,14 +109,6 @@ func (c *Client) IterateServicePrincipals(ctx context.Context, f func(principal return iterateSimple(c, ctx, "servicePrincipals", f) } -// IterateUserMembership lists all group memberships for a given user ID as directory objects. -// `f` will be called for each directory object in the result set. -// if `f` returns `false`, the iteration is stopped (equivalent to `break` in a normal loop). -// Ref: [https://learn.microsoft.com/en-us/graph/api/group-list-memberof]. -func (c *Client) IterateUserMembership(ctx context.Context, userID string, f func(object *DirectoryObject) bool) error { - return iterateSimple(c, ctx, path.Join("users", userID, "memberOf"), f) -} - // IterateGroupMembers lists all members for the given Entra ID group using pagination. // `f` will be called for each object in the result set. // if `f` returns `false`, the iteration is stopped (equivalent to `break` in a normal loop). diff --git a/lib/utils/slice.go b/lib/utils/slice.go index 8b4f73b9543d5..4009277ceef50 100644 --- a/lib/utils/slice.go +++ b/lib/utils/slice.go @@ -142,17 +142,3 @@ func FromSlice[T any](r []T, key func(T) string) map[string]T { return out } - -// DeduplicateKey returns a deduplicated slice by comparing key values from the key function -func DeduplicateKey[T any](s []T, key func(T) string) []T { - out := make([]T, 0, len(s)) - seen := make(map[string]struct{}) - for _, v := range s { - if _, ok := seen[key(v)]; ok { - continue - } - seen[key(v)] = struct{}{} - out = append(out, v) - } - return out -} diff --git a/lib/utils/slice_test.go b/lib/utils/slice_test.go index fce1f113025d1..76f4a1dd1a29d 100644 --- a/lib/utils/slice_test.go +++ b/lib/utils/slice_test.go @@ -19,7 +19,6 @@ package utils import ( - "fmt" "testing" "github.com/stretchr/testify/require" @@ -42,92 +41,3 @@ func TestSlice(t *testing.T) { pool.Put(slice) } } - -// TestDuplicateKey tests slice deduplication via key function -func TestDeduplicateKey(t *testing.T) { - t.Parallel() - - stringTests := []struct { - name string - slice []string - keyFn func(string) string - expected []string - }{ - { - name: "EmptyStringSlice", - slice: []string{}, - keyFn: func(s string) string { return s }, - expected: []string{}, - }, - { - name: "NoStringDuplicates", - slice: []string{"foo", "bar", "baz"}, - keyFn: func(s string) string { return s }, - expected: []string{"foo", "bar", "baz"}, - }, - { - name: "StringDuplicates", - slice: []string{"foo", "bar", "bar", "bar", "baz", "baz"}, - keyFn: func(s string) string { return s }, - expected: []string{"foo", "bar", "baz"}, - }, - { - name: "StringDuplicatesWeirdKeyFn", - slice: []string{"foo", "bar", "bar", "bar", "baz", "baz"}, - keyFn: func(s string) string { return "huh" }, - expected: []string{"foo"}, - }, - } - for _, tt := range stringTests { - t.Run(tt.name, func(t *testing.T) { - res := DeduplicateKey(tt.slice, tt.keyFn) - require.Equal(t, tt.expected, res) - }) - } - - type dedupeStruct struct { - a string - b int - c bool - } - dedupeStructKeyFn := func(d dedupeStruct) string { return fmt.Sprintf("%s:%d:%v", d.a, d.b, d.c) } - structTests := []struct { - name string - slice []dedupeStruct - keyFn func(d dedupeStruct) string - expected []dedupeStruct - }{ - { - name: "EmptySlice", - slice: []dedupeStruct{}, - keyFn: dedupeStructKeyFn, - expected: []dedupeStruct{}, - }, - { - name: "NoStructDuplicates", - slice: []dedupeStruct{ - {a: "foo", b: 1, c: true}, - {a: "foo", b: 1, c: false}, - {a: "foo", b: 2, c: true}, - {a: "bar", b: 1, c: true}, - {a: "bar", b: 1, c: false}, - {a: "bar", b: 2, c: true}, - }, - keyFn: dedupeStructKeyFn, - expected: []dedupeStruct{ - {a: "foo", b: 1, c: true}, - {a: "foo", b: 1, c: false}, - {a: "foo", b: 2, c: true}, - {a: "bar", b: 1, c: true}, - {a: "bar", b: 1, c: false}, - {a: "bar", b: 2, c: true}, - }, - }, - } - for _, tt := range structTests { - t.Run(tt.name, func(t *testing.T) { - res := DeduplicateKey(tt.slice, tt.keyFn) - require.Equal(t, tt.expected, res) - }) - } -} From 1e35ed2fc6738fdd9b17e173b748eae8e6eba408 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Fri, 10 Jan 2025 10:22:11 -0600 Subject: [PATCH 32/46] e ref update --- e | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e b/e index 052b9c2436c85..fe3b9e44eaee9 160000 --- a/e +++ b/e @@ -1 +1 @@ -Subproject commit 052b9c2436c8509628889751d88fc5410763cca2 +Subproject commit fe3b9e44eaee95db7dbb527a52ac064b6186e56a From e2f6e249b63e97ada0a9531d74bd169dd7cd3355 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Sat, 18 Jan 2025 12:02:04 -0600 Subject: [PATCH 33/46] Invoking token generation and returning the response --- .../integration/integrationv1/azureoidc.go | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 lib/auth/integration/integrationv1/azureoidc.go diff --git a/lib/auth/integration/integrationv1/azureoidc.go b/lib/auth/integration/integrationv1/azureoidc.go new file mode 100644 index 0000000000000..b81ad3b31c6d0 --- /dev/null +++ b/lib/auth/integration/integrationv1/azureoidc.go @@ -0,0 +1,22 @@ +package integrationv1 + +import ( + "context" + integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" + "github.com/gravitational/teleport/lib/integrations/azureoidc" + "github.com/gravitational/trace" +) + +func (s *Service) GenerateAzureOIDCToken(ctx context.Context, req *integrationpb.GenerateAzureOIDCTokenRequest) (*integrationpb.GenerateAzureOIDCTokenResponse, error) { + _, err := s.cache.GetIntegration(ctx, req.GetIntegration()) + if err != nil { + return nil, trace.Wrap(err) + } + 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 +} From dc9c000fab8aa3405eb1e62f58969312ba873739 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Sat, 18 Jan 2025 11:25:12 -0600 Subject: [PATCH 34/46] Quick test with a message to make sure RPC is invoked --- lib/auth/integration/integrationv1/azureoidc.go | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/lib/auth/integration/integrationv1/azureoidc.go b/lib/auth/integration/integrationv1/azureoidc.go index b81ad3b31c6d0..71de94f2b3839 100644 --- a/lib/auth/integration/integrationv1/azureoidc.go +++ b/lib/auth/integration/integrationv1/azureoidc.go @@ -2,21 +2,11 @@ package integrationv1 import ( "context" + "fmt" integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" - "github.com/gravitational/teleport/lib/integrations/azureoidc" - "github.com/gravitational/trace" ) func (s *Service) GenerateAzureOIDCToken(ctx context.Context, req *integrationpb.GenerateAzureOIDCTokenRequest) (*integrationpb.GenerateAzureOIDCTokenResponse, error) { - _, err := s.cache.GetIntegration(ctx, req.GetIntegration()) - if err != nil { - return nil, trace.Wrap(err) - } - 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 + fmt.Printf("============= GENERATING AZURE TOKEN?!\n") + return nil, nil } From 738cee6d94f9cda66b9d96bd37af078e40d67d63 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Fri, 17 Jan 2025 18:53:10 -0600 Subject: [PATCH 35/46] Skeleton of new Azure OIDC RPC call --- api/client/client.go | 11 + .../integration/v1/integration_service.pb.go | 395 +++++++++++------- .../v1/integration_service_grpc.pb.go | 40 ++ .../integration/v1/integration_service.proto | 17 + lib/auth/auth.go | 5 + lib/auth/authclient/api.go | 7 + lib/auth/authclient/clt.go | 3 + .../integration/integrationv1/azureoidc.go | 2 - lib/services/integration.go | 2 + 9 files changed, 340 insertions(+), 142 deletions(-) diff --git a/api/client/client.go b/api/client/client.go index 2daddc81d9777..81e79a5171f43 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -4835,6 +4835,17 @@ func (c *Client) GenerateAWSOIDCToken(ctx context.Context, integration string) ( return resp.GetToken(), nil } +func (c *Client) GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) { + resp, err := c.integrationsClient().GenerateAzureOIDCToken(ctx, &integrationpb.GenerateAzureOIDCTokenRequest{ + Integration: integration, + }) + if err != nil { + return "", trace.Wrap(err) + } + + return resp.GetToken(), nil +} + // PluginsClient returns an unadorned Plugins client, using the underlying // Auth gRPC connection. // Clients connecting to non-Enterprise clusters, or older Teleport versions, diff --git a/api/gen/proto/go/teleport/integration/v1/integration_service.pb.go b/api/gen/proto/go/teleport/integration/v1/integration_service.pb.go index ed4f0a44b7937..f73d6e83a11ad 100644 --- a/api/gen/proto/go/teleport/integration/v1/integration_service.pb.go +++ b/api/gen/proto/go/teleport/integration/v1/integration_service.pb.go @@ -487,6 +487,100 @@ func (x *GenerateAWSOIDCTokenResponse) GetToken() string { return "" } +// GenerateAzureOIDCTokenRequest are the parameters used to request an AWS OIDC +// Integration token. +type GenerateAzureOIDCTokenRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Integration is the Azure OIDC Integration name. + // Required. + Integration string `protobuf:"bytes,2,opt,name=integration,proto3" json:"integration,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GenerateAzureOIDCTokenRequest) Reset() { + *x = GenerateAzureOIDCTokenRequest{} + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GenerateAzureOIDCTokenRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenerateAzureOIDCTokenRequest) ProtoMessage() {} + +func (x *GenerateAzureOIDCTokenRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenerateAzureOIDCTokenRequest.ProtoReflect.Descriptor instead. +func (*GenerateAzureOIDCTokenRequest) Descriptor() ([]byte, []int) { + return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{9} +} + +func (x *GenerateAzureOIDCTokenRequest) GetIntegration() string { + if x != nil { + return x.Integration + } + return "" +} + +// GenerateAzureOIDCTokenResponse contains a signed Azure OIDC Integration token. +type GenerateAzureOIDCTokenResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Token is the signed JWT ready to be used + Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GenerateAzureOIDCTokenResponse) Reset() { + *x = GenerateAzureOIDCTokenResponse{} + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GenerateAzureOIDCTokenResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenerateAzureOIDCTokenResponse) ProtoMessage() {} + +func (x *GenerateAzureOIDCTokenResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenerateAzureOIDCTokenResponse.ProtoReflect.Descriptor instead. +func (*GenerateAzureOIDCTokenResponse) Descriptor() ([]byte, []int) { + return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{10} +} + +func (x *GenerateAzureOIDCTokenResponse) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + // GenerateGitHubUserCertRequest is a request to sign a client certificate used by // GitHub integration to authenticate with GitHub enterprise. type GenerateGitHubUserCertRequest struct { @@ -507,7 +601,7 @@ type GenerateGitHubUserCertRequest struct { func (x *GenerateGitHubUserCertRequest) Reset() { *x = GenerateGitHubUserCertRequest{} - mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[9] + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -519,7 +613,7 @@ func (x *GenerateGitHubUserCertRequest) String() string { func (*GenerateGitHubUserCertRequest) ProtoMessage() {} func (x *GenerateGitHubUserCertRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[9] + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -532,7 +626,7 @@ func (x *GenerateGitHubUserCertRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GenerateGitHubUserCertRequest.ProtoReflect.Descriptor instead. func (*GenerateGitHubUserCertRequest) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{9} + return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{11} } func (x *GenerateGitHubUserCertRequest) GetIntegration() string { @@ -581,7 +675,7 @@ type GenerateGitHubUserCertResponse struct { func (x *GenerateGitHubUserCertResponse) Reset() { *x = GenerateGitHubUserCertResponse{} - mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[10] + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -593,7 +687,7 @@ func (x *GenerateGitHubUserCertResponse) String() string { func (*GenerateGitHubUserCertResponse) ProtoMessage() {} func (x *GenerateGitHubUserCertResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[10] + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -606,7 +700,7 @@ func (x *GenerateGitHubUserCertResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GenerateGitHubUserCertResponse.ProtoReflect.Descriptor instead. func (*GenerateGitHubUserCertResponse) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{10} + return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{12} } func (x *GenerateGitHubUserCertResponse) GetAuthorizedKey() []byte { @@ -628,7 +722,7 @@ type ExportIntegrationCertAuthoritiesRequest struct { func (x *ExportIntegrationCertAuthoritiesRequest) Reset() { *x = ExportIntegrationCertAuthoritiesRequest{} - mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[11] + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -640,7 +734,7 @@ func (x *ExportIntegrationCertAuthoritiesRequest) String() string { func (*ExportIntegrationCertAuthoritiesRequest) ProtoMessage() {} func (x *ExportIntegrationCertAuthoritiesRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[11] + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -653,7 +747,7 @@ func (x *ExportIntegrationCertAuthoritiesRequest) ProtoReflect() protoreflect.Me // Deprecated: Use ExportIntegrationCertAuthoritiesRequest.ProtoReflect.Descriptor instead. func (*ExportIntegrationCertAuthoritiesRequest) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{11} + return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{13} } func (x *ExportIntegrationCertAuthoritiesRequest) GetIntegration() string { @@ -675,7 +769,7 @@ type ExportIntegrationCertAuthoritiesResponse struct { func (x *ExportIntegrationCertAuthoritiesResponse) Reset() { *x = ExportIntegrationCertAuthoritiesResponse{} - mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[12] + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -687,7 +781,7 @@ func (x *ExportIntegrationCertAuthoritiesResponse) String() string { func (*ExportIntegrationCertAuthoritiesResponse) ProtoMessage() {} func (x *ExportIntegrationCertAuthoritiesResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[12] + mi := &file_teleport_integration_v1_integration_service_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -700,7 +794,7 @@ func (x *ExportIntegrationCertAuthoritiesResponse) ProtoReflect() protoreflect.M // Deprecated: Use ExportIntegrationCertAuthoritiesResponse.ProtoReflect.Descriptor instead. func (*ExportIntegrationCertAuthoritiesResponse) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{12} + return file_teleport_integration_v1_integration_service_proto_rawDescGZIP(), []int{14} } func (x *ExportIntegrationCertAuthoritiesResponse) GetCertAuthorities() *types.CAKeySet { @@ -765,107 +859,124 @@ var file_teleport_integration_v1_integration_service_proto_rawDesc = []byte{ 0x1c, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x22, 0xbd, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, - 0x74, 0x74, 0x6c, 0x22, 0x47, 0x0a, 0x1e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x47, - 0x69, 0x74, 0x48, 0x75, 0x62, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x7a, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x22, 0x4b, 0x0a, 0x27, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, - 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x66, 0x0a, 0x28, 0x45, 0x78, 0x70, - 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x65, - 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x41, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, - 0x52, 0x0f, 0x63, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x32, 0xa5, 0x08, 0x0a, 0x12, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, - 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, - 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x56, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x65, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x12, 0x5c, 0x0a, 0x11, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x12, 0x5c, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, - 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x12, 0x5e, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x67, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x66, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, - 0x6c, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, + 0x6b, 0x65, 0x6e, 0x22, 0x41, 0x0a, 0x1d, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, + 0x7a, 0x75, 0x72, 0x65, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x36, 0x0a, 0x1e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xbd, + 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x47, 0x69, 0x74, 0x48, 0x75, + 0x62, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, + 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, + 0x64, 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x22, 0x47, + 0x0a, 0x1e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, + 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x22, 0x4b, 0x0a, 0x27, 0x45, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x65, 0x72, 0x74, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x66, 0x0a, 0x28, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x3a, 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x43, 0x41, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x52, 0x0f, 0x63, 0x65, 0x72, + 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x32, 0xb1, 0x09, 0x0a, + 0x12, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, - 0x6c, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x83, 0x01, - 0x0a, 0x14, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, - 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x34, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, - 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x12, 0x36, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x55, - 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0xa7, 0x01, 0x0a, 0x20, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x12, 0x40, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x5a, 0x5a, 0x58, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x65, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x56, 0x31, 0x12, 0x5c, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x56, 0x31, 0x12, 0x5c, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, + 0x12, 0x5e, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x66, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x49, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x49, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x83, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x12, 0x34, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, + 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, + 0x01, 0x0a, 0x16, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x7a, 0x75, 0x72, 0x65, + 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x36, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x7a, 0x75, 0x72, + 0x65, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x16, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x55, 0x73, 0x65, + 0x72, 0x43, 0x65, 0x72, 0x74, 0x12, 0x36, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x55, 0x73, + 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa7, 0x01, 0x0a, 0x20, 0x45, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x65, 0x72, 0x74, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x40, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x74, 0x65, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x5a, 0x5a, 0x58, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, + 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x3b, 0x69, + 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -880,7 +991,7 @@ func file_teleport_integration_v1_integration_service_proto_rawDescGZIP() []byte return file_teleport_integration_v1_integration_service_proto_rawDescData } -var file_teleport_integration_v1_integration_service_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_teleport_integration_v1_integration_service_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_teleport_integration_v1_integration_service_proto_goTypes = []any{ (*ListIntegrationsRequest)(nil), // 0: teleport.integration.v1.ListIntegrationsRequest (*ListIntegrationsResponse)(nil), // 1: teleport.integration.v1.ListIntegrationsResponse @@ -891,21 +1002,23 @@ var file_teleport_integration_v1_integration_service_proto_goTypes = []any{ (*DeleteAllIntegrationsRequest)(nil), // 6: teleport.integration.v1.DeleteAllIntegrationsRequest (*GenerateAWSOIDCTokenRequest)(nil), // 7: teleport.integration.v1.GenerateAWSOIDCTokenRequest (*GenerateAWSOIDCTokenResponse)(nil), // 8: teleport.integration.v1.GenerateAWSOIDCTokenResponse - (*GenerateGitHubUserCertRequest)(nil), // 9: teleport.integration.v1.GenerateGitHubUserCertRequest - (*GenerateGitHubUserCertResponse)(nil), // 10: teleport.integration.v1.GenerateGitHubUserCertResponse - (*ExportIntegrationCertAuthoritiesRequest)(nil), // 11: teleport.integration.v1.ExportIntegrationCertAuthoritiesRequest - (*ExportIntegrationCertAuthoritiesResponse)(nil), // 12: teleport.integration.v1.ExportIntegrationCertAuthoritiesResponse - (*types.IntegrationV1)(nil), // 13: types.IntegrationV1 - (*durationpb.Duration)(nil), // 14: google.protobuf.Duration - (*types.CAKeySet)(nil), // 15: types.CAKeySet - (*emptypb.Empty)(nil), // 16: google.protobuf.Empty + (*GenerateAzureOIDCTokenRequest)(nil), // 9: teleport.integration.v1.GenerateAzureOIDCTokenRequest + (*GenerateAzureOIDCTokenResponse)(nil), // 10: teleport.integration.v1.GenerateAzureOIDCTokenResponse + (*GenerateGitHubUserCertRequest)(nil), // 11: teleport.integration.v1.GenerateGitHubUserCertRequest + (*GenerateGitHubUserCertResponse)(nil), // 12: teleport.integration.v1.GenerateGitHubUserCertResponse + (*ExportIntegrationCertAuthoritiesRequest)(nil), // 13: teleport.integration.v1.ExportIntegrationCertAuthoritiesRequest + (*ExportIntegrationCertAuthoritiesResponse)(nil), // 14: teleport.integration.v1.ExportIntegrationCertAuthoritiesResponse + (*types.IntegrationV1)(nil), // 15: types.IntegrationV1 + (*durationpb.Duration)(nil), // 16: google.protobuf.Duration + (*types.CAKeySet)(nil), // 17: types.CAKeySet + (*emptypb.Empty)(nil), // 18: google.protobuf.Empty } var file_teleport_integration_v1_integration_service_proto_depIdxs = []int32{ - 13, // 0: teleport.integration.v1.ListIntegrationsResponse.integrations:type_name -> types.IntegrationV1 - 13, // 1: teleport.integration.v1.CreateIntegrationRequest.integration:type_name -> types.IntegrationV1 - 13, // 2: teleport.integration.v1.UpdateIntegrationRequest.integration:type_name -> types.IntegrationV1 - 14, // 3: teleport.integration.v1.GenerateGitHubUserCertRequest.ttl:type_name -> google.protobuf.Duration - 15, // 4: teleport.integration.v1.ExportIntegrationCertAuthoritiesResponse.cert_authorities:type_name -> types.CAKeySet + 15, // 0: teleport.integration.v1.ListIntegrationsResponse.integrations:type_name -> types.IntegrationV1 + 15, // 1: teleport.integration.v1.CreateIntegrationRequest.integration:type_name -> types.IntegrationV1 + 15, // 2: teleport.integration.v1.UpdateIntegrationRequest.integration:type_name -> types.IntegrationV1 + 16, // 3: teleport.integration.v1.GenerateGitHubUserCertRequest.ttl:type_name -> google.protobuf.Duration + 17, // 4: teleport.integration.v1.ExportIntegrationCertAuthoritiesResponse.cert_authorities:type_name -> types.CAKeySet 0, // 5: teleport.integration.v1.IntegrationService.ListIntegrations:input_type -> teleport.integration.v1.ListIntegrationsRequest 2, // 6: teleport.integration.v1.IntegrationService.GetIntegration:input_type -> teleport.integration.v1.GetIntegrationRequest 3, // 7: teleport.integration.v1.IntegrationService.CreateIntegration:input_type -> teleport.integration.v1.CreateIntegrationRequest @@ -913,19 +1026,21 @@ var file_teleport_integration_v1_integration_service_proto_depIdxs = []int32{ 5, // 9: teleport.integration.v1.IntegrationService.DeleteIntegration:input_type -> teleport.integration.v1.DeleteIntegrationRequest 6, // 10: teleport.integration.v1.IntegrationService.DeleteAllIntegrations:input_type -> teleport.integration.v1.DeleteAllIntegrationsRequest 7, // 11: teleport.integration.v1.IntegrationService.GenerateAWSOIDCToken:input_type -> teleport.integration.v1.GenerateAWSOIDCTokenRequest - 9, // 12: teleport.integration.v1.IntegrationService.GenerateGitHubUserCert:input_type -> teleport.integration.v1.GenerateGitHubUserCertRequest - 11, // 13: teleport.integration.v1.IntegrationService.ExportIntegrationCertAuthorities:input_type -> teleport.integration.v1.ExportIntegrationCertAuthoritiesRequest - 1, // 14: teleport.integration.v1.IntegrationService.ListIntegrations:output_type -> teleport.integration.v1.ListIntegrationsResponse - 13, // 15: teleport.integration.v1.IntegrationService.GetIntegration:output_type -> types.IntegrationV1 - 13, // 16: teleport.integration.v1.IntegrationService.CreateIntegration:output_type -> types.IntegrationV1 - 13, // 17: teleport.integration.v1.IntegrationService.UpdateIntegration:output_type -> types.IntegrationV1 - 16, // 18: teleport.integration.v1.IntegrationService.DeleteIntegration:output_type -> google.protobuf.Empty - 16, // 19: teleport.integration.v1.IntegrationService.DeleteAllIntegrations:output_type -> google.protobuf.Empty - 8, // 20: teleport.integration.v1.IntegrationService.GenerateAWSOIDCToken:output_type -> teleport.integration.v1.GenerateAWSOIDCTokenResponse - 10, // 21: teleport.integration.v1.IntegrationService.GenerateGitHubUserCert:output_type -> teleport.integration.v1.GenerateGitHubUserCertResponse - 12, // 22: teleport.integration.v1.IntegrationService.ExportIntegrationCertAuthorities:output_type -> teleport.integration.v1.ExportIntegrationCertAuthoritiesResponse - 14, // [14:23] is the sub-list for method output_type - 5, // [5:14] is the sub-list for method input_type + 9, // 12: teleport.integration.v1.IntegrationService.GenerateAzureOIDCToken:input_type -> teleport.integration.v1.GenerateAzureOIDCTokenRequest + 11, // 13: teleport.integration.v1.IntegrationService.GenerateGitHubUserCert:input_type -> teleport.integration.v1.GenerateGitHubUserCertRequest + 13, // 14: teleport.integration.v1.IntegrationService.ExportIntegrationCertAuthorities:input_type -> teleport.integration.v1.ExportIntegrationCertAuthoritiesRequest + 1, // 15: teleport.integration.v1.IntegrationService.ListIntegrations:output_type -> teleport.integration.v1.ListIntegrationsResponse + 15, // 16: teleport.integration.v1.IntegrationService.GetIntegration:output_type -> types.IntegrationV1 + 15, // 17: teleport.integration.v1.IntegrationService.CreateIntegration:output_type -> types.IntegrationV1 + 15, // 18: teleport.integration.v1.IntegrationService.UpdateIntegration:output_type -> types.IntegrationV1 + 18, // 19: teleport.integration.v1.IntegrationService.DeleteIntegration:output_type -> google.protobuf.Empty + 18, // 20: teleport.integration.v1.IntegrationService.DeleteAllIntegrations:output_type -> google.protobuf.Empty + 8, // 21: teleport.integration.v1.IntegrationService.GenerateAWSOIDCToken:output_type -> teleport.integration.v1.GenerateAWSOIDCTokenResponse + 10, // 22: teleport.integration.v1.IntegrationService.GenerateAzureOIDCToken:output_type -> teleport.integration.v1.GenerateAzureOIDCTokenResponse + 12, // 23: teleport.integration.v1.IntegrationService.GenerateGitHubUserCert:output_type -> teleport.integration.v1.GenerateGitHubUserCertResponse + 14, // 24: teleport.integration.v1.IntegrationService.ExportIntegrationCertAuthorities:output_type -> teleport.integration.v1.ExportIntegrationCertAuthoritiesResponse + 15, // [15:25] is the sub-list for method output_type + 5, // [5:15] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name 5, // [5:5] is the sub-list for extension extendee 0, // [0:5] is the sub-list for field type_name @@ -942,7 +1057,7 @@ func file_teleport_integration_v1_integration_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_teleport_integration_v1_integration_service_proto_rawDesc, NumEnums: 0, - NumMessages: 13, + NumMessages: 15, NumExtensions: 0, NumServices: 1, }, diff --git a/api/gen/proto/go/teleport/integration/v1/integration_service_grpc.pb.go b/api/gen/proto/go/teleport/integration/v1/integration_service_grpc.pb.go index e003922829236..7dfadc9f20be6 100644 --- a/api/gen/proto/go/teleport/integration/v1/integration_service_grpc.pb.go +++ b/api/gen/proto/go/teleport/integration/v1/integration_service_grpc.pb.go @@ -42,6 +42,7 @@ const ( IntegrationService_DeleteIntegration_FullMethodName = "/teleport.integration.v1.IntegrationService/DeleteIntegration" IntegrationService_DeleteAllIntegrations_FullMethodName = "/teleport.integration.v1.IntegrationService/DeleteAllIntegrations" IntegrationService_GenerateAWSOIDCToken_FullMethodName = "/teleport.integration.v1.IntegrationService/GenerateAWSOIDCToken" + IntegrationService_GenerateAzureOIDCToken_FullMethodName = "/teleport.integration.v1.IntegrationService/GenerateAzureOIDCToken" IntegrationService_GenerateGitHubUserCert_FullMethodName = "/teleport.integration.v1.IntegrationService/GenerateGitHubUserCert" IntegrationService_ExportIntegrationCertAuthorities_FullMethodName = "/teleport.integration.v1.IntegrationService/ExportIntegrationCertAuthorities" ) @@ -67,6 +68,8 @@ type IntegrationServiceClient interface { DeleteAllIntegrations(ctx context.Context, in *DeleteAllIntegrationsRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // GenerateAWSOIDCToken generates a token to be used when executing an AWS OIDC Integration action. GenerateAWSOIDCToken(ctx context.Context, in *GenerateAWSOIDCTokenRequest, opts ...grpc.CallOption) (*GenerateAWSOIDCTokenResponse, error) + // GenerateAzureOIDCToken generates a token to be used when executing an Azure OIDC Integration action. + GenerateAzureOIDCToken(ctx context.Context, in *GenerateAzureOIDCTokenRequest, opts ...grpc.CallOption) (*GenerateAzureOIDCTokenResponse, error) // GenerateGitHubUserCert signs a SSH certificate for GitHub integration. GenerateGitHubUserCert(ctx context.Context, in *GenerateGitHubUserCertRequest, opts ...grpc.CallOption) (*GenerateGitHubUserCertResponse, error) // ExportIntegrationCertAuthorities exports cert authorities for an integration. @@ -151,6 +154,16 @@ func (c *integrationServiceClient) GenerateAWSOIDCToken(ctx context.Context, in return out, nil } +func (c *integrationServiceClient) GenerateAzureOIDCToken(ctx context.Context, in *GenerateAzureOIDCTokenRequest, opts ...grpc.CallOption) (*GenerateAzureOIDCTokenResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GenerateAzureOIDCTokenResponse) + err := c.cc.Invoke(ctx, IntegrationService_GenerateAzureOIDCToken_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *integrationServiceClient) GenerateGitHubUserCert(ctx context.Context, in *GenerateGitHubUserCertRequest, opts ...grpc.CallOption) (*GenerateGitHubUserCertResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GenerateGitHubUserCertResponse) @@ -192,6 +205,8 @@ type IntegrationServiceServer interface { DeleteAllIntegrations(context.Context, *DeleteAllIntegrationsRequest) (*emptypb.Empty, error) // GenerateAWSOIDCToken generates a token to be used when executing an AWS OIDC Integration action. GenerateAWSOIDCToken(context.Context, *GenerateAWSOIDCTokenRequest) (*GenerateAWSOIDCTokenResponse, error) + // GenerateAzureOIDCToken generates a token to be used when executing an Azure OIDC Integration action. + GenerateAzureOIDCToken(context.Context, *GenerateAzureOIDCTokenRequest) (*GenerateAzureOIDCTokenResponse, error) // GenerateGitHubUserCert signs a SSH certificate for GitHub integration. GenerateGitHubUserCert(context.Context, *GenerateGitHubUserCertRequest) (*GenerateGitHubUserCertResponse, error) // ExportIntegrationCertAuthorities exports cert authorities for an integration. @@ -227,6 +242,9 @@ func (UnimplementedIntegrationServiceServer) DeleteAllIntegrations(context.Conte func (UnimplementedIntegrationServiceServer) GenerateAWSOIDCToken(context.Context, *GenerateAWSOIDCTokenRequest) (*GenerateAWSOIDCTokenResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GenerateAWSOIDCToken not implemented") } +func (UnimplementedIntegrationServiceServer) GenerateAzureOIDCToken(context.Context, *GenerateAzureOIDCTokenRequest) (*GenerateAzureOIDCTokenResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GenerateAzureOIDCToken not implemented") +} func (UnimplementedIntegrationServiceServer) GenerateGitHubUserCert(context.Context, *GenerateGitHubUserCertRequest) (*GenerateGitHubUserCertResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GenerateGitHubUserCert not implemented") } @@ -380,6 +398,24 @@ func _IntegrationService_GenerateAWSOIDCToken_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _IntegrationService_GenerateAzureOIDCToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GenerateAzureOIDCTokenRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IntegrationServiceServer).GenerateAzureOIDCToken(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: IntegrationService_GenerateAzureOIDCToken_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IntegrationServiceServer).GenerateAzureOIDCToken(ctx, req.(*GenerateAzureOIDCTokenRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _IntegrationService_GenerateGitHubUserCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GenerateGitHubUserCertRequest) if err := dec(in); err != nil { @@ -451,6 +487,10 @@ var IntegrationService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GenerateAWSOIDCToken", Handler: _IntegrationService_GenerateAWSOIDCToken_Handler, }, + { + MethodName: "GenerateAzureOIDCToken", + Handler: _IntegrationService_GenerateAzureOIDCToken_Handler, + }, { MethodName: "GenerateGitHubUserCert", Handler: _IntegrationService_GenerateGitHubUserCert_Handler, diff --git a/api/proto/teleport/integration/v1/integration_service.proto b/api/proto/teleport/integration/v1/integration_service.proto index 0528f521f684e..fe5190df71449 100644 --- a/api/proto/teleport/integration/v1/integration_service.proto +++ b/api/proto/teleport/integration/v1/integration_service.proto @@ -46,6 +46,9 @@ service IntegrationService { // GenerateAWSOIDCToken generates a token to be used when executing an AWS OIDC Integration action. rpc GenerateAWSOIDCToken(GenerateAWSOIDCTokenRequest) returns (GenerateAWSOIDCTokenResponse); + // GenerateAzureOIDCToken generates a token to be used when executing an Azure OIDC Integration action. + rpc GenerateAzureOIDCToken(GenerateAzureOIDCTokenRequest) returns (GenerateAzureOIDCTokenResponse); + // GenerateGitHubUserCert signs a SSH certificate for GitHub integration. rpc GenerateGitHubUserCert(GenerateGitHubUserCertRequest) returns (GenerateGitHubUserCertResponse); @@ -119,6 +122,20 @@ message GenerateAWSOIDCTokenResponse { string token = 1; } +// GenerateAzureOIDCTokenRequest are the parameters used to request an AWS OIDC +// Integration token. +message GenerateAzureOIDCTokenRequest { + // Integration is the Azure OIDC Integration name. + // Required. + string integration = 2; +} + +// GenerateAzureOIDCTokenResponse contains a signed Azure OIDC Integration token. +message GenerateAzureOIDCTokenResponse { + // Token is the signed JWT ready to be used + string token = 1; +} + // GenerateGitHubUserCertRequest is a request to sign a client certificate used by // GitHub integration to authenticate with GitHub enterprise. message GenerateGitHubUserCertRequest { diff --git a/lib/auth/auth.go b/lib/auth/auth.go index b500e7eac688c..a8b341a5df3de 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -749,6 +749,11 @@ func (r *Services) GenerateAWSOIDCToken(ctx context.Context, integration string) return r.IntegrationsTokenGenerator.GenerateAWSOIDCToken(ctx, integration) } +// GenerateAzureOIDCToken generates a token to be used to execute an AWS OIDC Integration action. +func (r *Services) GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) { + return r.IntegrationsTokenGenerator.GenerateAzureOIDCToken(ctx, integration) +} + var ( generateRequestsCount = prometheus.NewCounter( prometheus.CounterOpts{ diff --git a/lib/auth/authclient/api.go b/lib/auth/authclient/api.go index 1776165eaea85..e59f2b73cc36c 100644 --- a/lib/auth/authclient/api.go +++ b/lib/auth/authclient/api.go @@ -760,6 +760,9 @@ type DiscoveryAccessPoint interface { // GenerateAWSOIDCToken generates a token to be used to execute an AWS OIDC Integration action. GenerateAWSOIDCToken(ctx context.Context, integration string) (string, error) + // GenerateAzureOIDCToken generates a token to be used to execute an Azure OIDC Integration action. + GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) + // EnrollEKSClusters enrolls EKS clusters into Teleport by installing teleport-kube-agent chart on the clusters. EnrollEKSClusters(context.Context, *integrationpb.EnrollEKSClustersRequest, ...grpc.CallOption) (*integrationpb.EnrollEKSClustersResponse, error) @@ -1437,6 +1440,10 @@ func (w *DiscoveryWrapper) GenerateAWSOIDCToken(ctx context.Context, integration return w.NoCache.GenerateAWSOIDCToken(ctx, integration) } +func (w *DiscoveryWrapper) GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) { + return w.NoCache.GenerateAzureOIDCToken(ctx, integration) +} + // EnrollEKSClusters enrolls EKS clusters into Teleport by installing teleport-kube-agent chart on the clusters. func (w *DiscoveryWrapper) EnrollEKSClusters(ctx context.Context, req *integrationpb.EnrollEKSClustersRequest, _ ...grpc.CallOption) (*integrationpb.EnrollEKSClustersResponse, error) { return w.NoCache.EnrollEKSClusters(ctx, req) diff --git a/lib/auth/authclient/clt.go b/lib/auth/authclient/clt.go index 4f17263feaab7..c2c84b2b79131 100644 --- a/lib/auth/authclient/clt.go +++ b/lib/auth/authclient/clt.go @@ -1703,6 +1703,9 @@ type ClientI interface { // GenerateAWSOIDCToken generates a token to be used to execute an AWS OIDC Integration action. GenerateAWSOIDCToken(ctx context.Context, integration string) (string, error) + // GenerateAzureOIDCToken generates a token to be used to execute an Azure OIDC Integration action. + GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) + // ResetAuthPreference resets cluster auth preference to defaults. ResetAuthPreference(ctx context.Context) error diff --git a/lib/auth/integration/integrationv1/azureoidc.go b/lib/auth/integration/integrationv1/azureoidc.go index 71de94f2b3839..ae144756a26ad 100644 --- a/lib/auth/integration/integrationv1/azureoidc.go +++ b/lib/auth/integration/integrationv1/azureoidc.go @@ -2,11 +2,9 @@ package integrationv1 import ( "context" - "fmt" integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" ) func (s *Service) GenerateAzureOIDCToken(ctx context.Context, req *integrationpb.GenerateAzureOIDCTokenRequest) (*integrationpb.GenerateAzureOIDCTokenResponse, error) { - fmt.Printf("============= GENERATING AZURE TOKEN?!\n") return nil, nil } diff --git a/lib/services/integration.go b/lib/services/integration.go index be495d385b4ab..bfe000113ee5c 100644 --- a/lib/services/integration.go +++ b/lib/services/integration.go @@ -52,6 +52,8 @@ type IntegrationsGetter interface { type IntegrationsTokenGenerator interface { // GenerateAWSOIDCToken generates a token to be used to execute an AWS OIDC Integration action. GenerateAWSOIDCToken(ctx context.Context, integration string) (string, error) + // GenerateAzureOIDCToken generates a token to be used to execute an Azure OIDC Integration action. + GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) } // MarshalIntegration marshals the Integration resource to JSON. From 71ce3224dd308bcf4e08f18c627538a0b3fd7190 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Sat, 18 Jan 2025 21:55:39 -0600 Subject: [PATCH 36/46] Fetching the Azure OIDC token during fetcher creation and establishing a credential assertion approach --- lib/auth/integration/integrationv1/azureoidc.go | 12 +++++++++++- lib/srv/discovery/discovery.go | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/auth/integration/integrationv1/azureoidc.go b/lib/auth/integration/integrationv1/azureoidc.go index ae144756a26ad..bdca0bb46d2f5 100644 --- a/lib/auth/integration/integrationv1/azureoidc.go +++ b/lib/auth/integration/integrationv1/azureoidc.go @@ -3,8 +3,18 @@ package integrationv1 import ( "context" integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" + "github.com/gravitational/teleport/lib/integrations/azureoidc" + "github.com/gravitational/trace" ) func (s *Service) GenerateAzureOIDCToken(ctx context.Context, req *integrationpb.GenerateAzureOIDCTokenRequest) (*integrationpb.GenerateAzureOIDCTokenResponse, error) { - return nil, nil + _, err := s.cache.GetIntegration(ctx, req.Integration) + if err != nil { + return nil, trace.Wrap(err) + } + 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 } diff --git a/lib/srv/discovery/discovery.go b/lib/srv/discovery/discovery.go index 4dd5eb77f59a3..67470c3816ce1 100644 --- a/lib/srv/discovery/discovery.go +++ b/lib/srv/discovery/discovery.go @@ -1832,7 +1832,7 @@ func (s *Server) upsertDynamicMatchers(ctx context.Context, dc *discoveryconfig. s.dynamicTAGAWSFetchers[dc.GetName()] = awsSyncMatchers s.muDynamicTAGAWSFetchers.Unlock() - azureSyncMatchers, err := s.accessGraphAzureFetchersFromMatchers(matchers, dc.GetName()) + azureSyncMatchers, err := s.accessGraphAzureFetchersFromMatchers(ctx, matchers, dc.GetName()) if err != nil { return trace.Wrap(err) } From 5a6006866515d82f628fb04d866d61b543fbc107 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Tue, 21 Jan 2025 16:40:37 -0600 Subject: [PATCH 37/46] PR feedback; restricting token requests to auth, discovery, and proxy roles. --- api/client/client.go | 1 + .../integration/v1/integration_service.proto | 4 +- lib/auth/auth.go | 2 +- lib/auth/authclient/api.go | 1 + .../integration/integrationv1/azureoidc.go | 36 +++++- .../integrationv1/azureoidc_test.go | 111 ++++++++++++++++++ 6 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 lib/auth/integration/integrationv1/azureoidc_test.go diff --git a/api/client/client.go b/api/client/client.go index 81e79a5171f43..4306ab1a619b0 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -4835,6 +4835,7 @@ func (c *Client) GenerateAWSOIDCToken(ctx context.Context, integration string) ( return resp.GetToken(), nil } +// GenerateAzureOIDCToken generates a token to be used when executing an Azure OIDC Integration action. func (c *Client) GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) { resp, err := c.integrationsClient().GenerateAzureOIDCToken(ctx, &integrationpb.GenerateAzureOIDCTokenRequest{ Integration: integration, diff --git a/api/proto/teleport/integration/v1/integration_service.proto b/api/proto/teleport/integration/v1/integration_service.proto index fe5190df71449..8eb0875f6443b 100644 --- a/api/proto/teleport/integration/v1/integration_service.proto +++ b/api/proto/teleport/integration/v1/integration_service.proto @@ -122,12 +122,12 @@ message GenerateAWSOIDCTokenResponse { string token = 1; } -// GenerateAzureOIDCTokenRequest are the parameters used to request an AWS OIDC +// GenerateAzureOIDCTokenRequest are the parameters used to request an Azure OIDC // Integration token. message GenerateAzureOIDCTokenRequest { // Integration is the Azure OIDC Integration name. // Required. - string integration = 2; + string integration = 1; } // GenerateAzureOIDCTokenResponse contains a signed Azure OIDC Integration token. diff --git a/lib/auth/auth.go b/lib/auth/auth.go index a8b341a5df3de..1e6f954b75b31 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -749,7 +749,7 @@ func (r *Services) GenerateAWSOIDCToken(ctx context.Context, integration string) return r.IntegrationsTokenGenerator.GenerateAWSOIDCToken(ctx, integration) } -// GenerateAzureOIDCToken generates a token to be used to execute an AWS OIDC Integration action. +// GenerateAzureOIDCToken generates a token to be used to execute an Azure OIDC Integration action. func (r *Services) GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) { return r.IntegrationsTokenGenerator.GenerateAzureOIDCToken(ctx, integration) } diff --git a/lib/auth/authclient/api.go b/lib/auth/authclient/api.go index e59f2b73cc36c..e0fb827b5aa3f 100644 --- a/lib/auth/authclient/api.go +++ b/lib/auth/authclient/api.go @@ -1440,6 +1440,7 @@ func (w *DiscoveryWrapper) GenerateAWSOIDCToken(ctx context.Context, integration return w.NoCache.GenerateAWSOIDCToken(ctx, integration) } +// GenerateAzureOIDCToken generates a token to be used to execute an Azure OIDC Integration action. func (w *DiscoveryWrapper) GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) { return w.NoCache.GenerateAzureOIDCToken(ctx, integration) } diff --git a/lib/auth/integration/integrationv1/azureoidc.go b/lib/auth/integration/integrationv1/azureoidc.go index bdca0bb46d2f5..f932c91e5ff12 100644 --- a/lib/auth/integration/integrationv1/azureoidc.go +++ b/lib/auth/integration/integrationv1/azureoidc.go @@ -1,20 +1,50 @@ +/* + * 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 . + */ + package integrationv1 import ( "context" 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" "github.com/gravitational/trace" ) +// 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) { - _, err := s.cache.GetIntegration(ctx, req.Integration) + authCtx, err := s.authorizer.Authorize(ctx) if err != nil { return nil, trace.Wrap(err) } - token, err := azureoidc.GenerateEntraOIDCToken(ctx, s.cache, s.keyStoreManager, s.clock) + _, err = s.cache.GetIntegration(ctx, req.Integration) if err != nil { return nil, trace.Wrap(err) } - return &integrationpb.GenerateAzureOIDCTokenResponse{Token: token}, nil + 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") } diff --git a/lib/auth/integration/integrationv1/azureoidc_test.go b/lib/auth/integration/integrationv1/azureoidc_test.go new file mode 100644 index 0000000000000..4ca9ac12a5541 --- /dev/null +++ b/lib/auth/integration/integrationv1/azureoidc_test.go @@ -0,0 +1,111 @@ +/* + * 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 . + */ + +package integrationv1 + +import ( + 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" + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" + "testing" +) + +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) + + }) +} From dc04d946a379a064cb832b4b1c7a22b1d5c53725 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 22 Jan 2025 13:49:43 -0600 Subject: [PATCH 38/46] Lint --- .../go/teleport/integration/v1/integration_service.pb.go | 6 +++--- lib/auth/integration/integrationv1/azureoidc.go | 4 +++- lib/auth/integration/integrationv1/azureoidc_test.go | 8 +++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/api/gen/proto/go/teleport/integration/v1/integration_service.pb.go b/api/gen/proto/go/teleport/integration/v1/integration_service.pb.go index f73d6e83a11ad..3440218d504a6 100644 --- a/api/gen/proto/go/teleport/integration/v1/integration_service.pb.go +++ b/api/gen/proto/go/teleport/integration/v1/integration_service.pb.go @@ -487,13 +487,13 @@ func (x *GenerateAWSOIDCTokenResponse) GetToken() string { return "" } -// GenerateAzureOIDCTokenRequest are the parameters used to request an AWS OIDC +// GenerateAzureOIDCTokenRequest are the parameters used to request an Azure OIDC // Integration token. type GenerateAzureOIDCTokenRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Integration is the Azure OIDC Integration name. // Required. - Integration string `protobuf:"bytes,2,opt,name=integration,proto3" json:"integration,omitempty"` + Integration string `protobuf:"bytes,1,opt,name=integration,proto3" json:"integration,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -862,7 +862,7 @@ var file_teleport_integration_v1_integration_service_proto_rawDesc = []byte{ 0x6b, 0x65, 0x6e, 0x22, 0x41, 0x0a, 0x1d, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x36, 0x0a, 0x1e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x4f, 0x49, 0x44, 0x43, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, diff --git a/lib/auth/integration/integrationv1/azureoidc.go b/lib/auth/integration/integrationv1/azureoidc.go index f932c91e5ff12..0db1fd50e59d6 100644 --- a/lib/auth/integration/integrationv1/azureoidc.go +++ b/lib/auth/integration/integrationv1/azureoidc.go @@ -20,11 +20,13 @@ 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" - "github.com/gravitational/trace" ) // GenerateAzureOIDCToken generates a token to be used to execute an Azure OIDC Integration action. diff --git a/lib/auth/integration/integrationv1/azureoidc_test.go b/lib/auth/integration/integrationv1/azureoidc_test.go index 4ca9ac12a5541..08398ee51a4b1 100644 --- a/lib/auth/integration/integrationv1/azureoidc_test.go +++ b/lib/auth/integration/integrationv1/azureoidc_test.go @@ -19,15 +19,17 @@ 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" - "github.com/gravitational/trace" - "github.com/stretchr/testify/require" - "testing" ) func TestGenerateAzureOIDCToken(t *testing.T) { From 7242fba91510083e33c4ba03b6ae70d1eb1be1b4 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 22 Jan 2025 14:01:06 -0600 Subject: [PATCH 39/46] Fixing mocks --- lib/srv/discovery/kube_integration_watcher_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/srv/discovery/kube_integration_watcher_test.go b/lib/srv/discovery/kube_integration_watcher_test.go index 3c7cbd57731fd..717e31b0d595e 100644 --- a/lib/srv/discovery/kube_integration_watcher_test.go +++ b/lib/srv/discovery/kube_integration_watcher_test.go @@ -525,6 +525,11 @@ func (m *mockIntegrationsTokenGenerator) GenerateAWSOIDCToken(ctx context.Contex return uuid.NewString(), nil } +// GenerateAzureOIDCToken generates a token to be used to execute an Azure OIDC Integration action. +func (m *mockIntegrationsTokenGenerator) GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) { + return uuid.NewString(), nil +} + type mockEnrollEKSClusterClient struct { createAccessEntry func(context.Context, *eks.CreateAccessEntryInput, ...func(*eks.Options)) (*eks.CreateAccessEntryOutput, error) associateAccessPolicy func(context.Context, *eks.AssociateAccessPolicyInput, ...func(*eks.Options)) (*eks.AssociateAccessPolicyOutput, error) From 384ab8ffa6b95cb133a10f7bca290803980d8c17 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 22 Jan 2025 14:02:44 -0600 Subject: [PATCH 40/46] Fix imports --- lib/srv/discovery/fetchers/azuresync/azure-sync.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/srv/discovery/fetchers/azuresync/azure-sync.go b/lib/srv/discovery/fetchers/azuresync/azure-sync.go index 53d4d4144c5cf..1db28d0aaca50 100644 --- a/lib/srv/discovery/fetchers/azuresync/azure-sync.go +++ b/lib/srv/discovery/fetchers/azuresync/azure-sync.go @@ -25,6 +25,7 @@ import ( "github.com/gravitational/trace" "golang.org/x/sync/errgroup" + "github.com/gravitational/teleport/api/types" accessgraphv1alpha "github.com/gravitational/teleport/gen/proto/go/accessgraph/v1alpha" "github.com/gravitational/teleport/lib/cloud/azure" "github.com/gravitational/teleport/lib/msgraph" From 8093659a70ddbf3a6b20da625e8cf4fc139d4f82 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 22 Jan 2025 14:17:58 -0600 Subject: [PATCH 41/46] Fix test --- lib/auth/integration/integrationv1/azureoidc_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/auth/integration/integrationv1/azureoidc_test.go b/lib/auth/integration/integrationv1/azureoidc_test.go index 08398ee51a4b1..f235d51538d71 100644 --- a/lib/auth/integration/integrationv1/azureoidc_test.go +++ b/lib/auth/integration/integrationv1/azureoidc_test.go @@ -108,6 +108,6 @@ func TestGenerateAzureOIDCToken(t *testing.T) { // Verify the Azure token using the JWT _, err = key.VerifyAzureToken(resp.Token) - + require.NoError(t, err) }) } From 770cafc17d2af1ce4593794e4e0ef4201153ea99 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Wed, 22 Jan 2025 20:24:41 -0600 Subject: [PATCH 42/46] Rebase fxes --- lib/srv/discovery/discovery.go | 2 +- lib/srv/discovery/fetchers/azuresync/azure-sync.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/srv/discovery/discovery.go b/lib/srv/discovery/discovery.go index 67470c3816ce1..4dd5eb77f59a3 100644 --- a/lib/srv/discovery/discovery.go +++ b/lib/srv/discovery/discovery.go @@ -1832,7 +1832,7 @@ func (s *Server) upsertDynamicMatchers(ctx context.Context, dc *discoveryconfig. s.dynamicTAGAWSFetchers[dc.GetName()] = awsSyncMatchers s.muDynamicTAGAWSFetchers.Unlock() - azureSyncMatchers, err := s.accessGraphAzureFetchersFromMatchers(ctx, matchers, dc.GetName()) + azureSyncMatchers, err := s.accessGraphAzureFetchersFromMatchers(matchers, dc.GetName()) if err != nil { return trace.Wrap(err) } diff --git a/lib/srv/discovery/fetchers/azuresync/azure-sync.go b/lib/srv/discovery/fetchers/azuresync/azure-sync.go index 1db28d0aaca50..53d4d4144c5cf 100644 --- a/lib/srv/discovery/fetchers/azuresync/azure-sync.go +++ b/lib/srv/discovery/fetchers/azuresync/azure-sync.go @@ -25,7 +25,6 @@ import ( "github.com/gravitational/trace" "golang.org/x/sync/errgroup" - "github.com/gravitational/teleport/api/types" accessgraphv1alpha "github.com/gravitational/teleport/gen/proto/go/accessgraph/v1alpha" "github.com/gravitational/teleport/lib/cloud/azure" "github.com/gravitational/teleport/lib/msgraph" From ebcdab8178f49bd6fc0906f42d0788320a4df631 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Thu, 23 Jan 2025 10:43:28 -0600 Subject: [PATCH 43/46] Adding back OIDC fetching, accidentally removed it during rebase --- lib/srv/discovery/access_graph_azure.go | 1 + .../fetchers/azuresync/azure-sync.go | 33 ++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/srv/discovery/access_graph_azure.go b/lib/srv/discovery/access_graph_azure.go index d7f911bb2a449..98192983617e7 100644 --- a/lib/srv/discovery/access_graph_azure.go +++ b/lib/srv/discovery/access_graph_azure.go @@ -392,6 +392,7 @@ func (s *Server) accessGraphAzureFetchersFromMatchers( SubscriptionID: matcher.SubscriptionID, Integration: matcher.Integration, DiscoveryConfigName: discoveryConfigName, + OIDCCredentials: s.AccessPoint, } fetcher, err := azuresync.NewFetcher(fetcherCfg, s.ctx) if err != nil { diff --git a/lib/srv/discovery/fetchers/azuresync/azure-sync.go b/lib/srv/discovery/fetchers/azuresync/azure-sync.go index 53d4d4144c5cf..65c5b6eda56c2 100644 --- a/lib/srv/discovery/fetchers/azuresync/azure-sync.go +++ b/lib/srv/discovery/fetchers/azuresync/azure-sync.go @@ -20,6 +20,7 @@ package azuresync import ( "context" + "github.com/gravitational/teleport/api/types" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/gravitational/trace" @@ -35,6 +36,11 @@ import ( // the number of resource types, we may increase this value or use some other approach to fetching concurrency. const fetcherConcurrency = 4 +type AzureOIDCCredentials interface { + GenerateAzureOIDCToken(ctx context.Context, integration string) (string, error) + GetIntegration(ctx context.Context, name string) (types.Integration, error) +} + // Config defines parameters required for fetching resources from Azure type Config struct { // SubscriptionID is the Azure subscriptipn ID @@ -43,6 +49,8 @@ type Config struct { Integration string // DiscoveryConfigName is the name of this Discovery configuration DiscoveryConfigName string + // OIDCCredentials provides methods for fetching OIDC credentials + OIDCCredentials AzureOIDCCredentials } // Resources represents the set of resources fetched from Azure @@ -80,10 +88,27 @@ type Fetcher struct { // NewFetcher returns a new fetcher based on configuration parameters func NewFetcher(cfg Config, ctx context.Context) (*Fetcher, error) { - // Establish the credential from the managed identity - cred, err := azidentity.NewDefaultAzureCredential(nil) - if err != nil { - return nil, trace.Wrap(err) + var cred msgraph.AzureTokenProvider + var err error + if cfg.Integration == "" { + // Establish the credential from the managed identity + cred, err = azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return nil, trace.Wrap(err) + } + } else { + // Establish the credential from OIDC credential assertion + integration, err := cfg.OIDCCredentials.GetIntegration(ctx, cfg.Integration) + if err != nil { + return nil, trace.Wrap(err) + } + azureIntegration := integration.GetAzureOIDCIntegrationSpec() + cred, err = azidentity.NewClientAssertionCredential(azureIntegration.TenantID, azureIntegration.ClientID, func(ctx context.Context) (string, error) { + return cfg.OIDCCredentials.GenerateAzureOIDCToken(ctx, cfg.Integration) + }, nil) + if err != nil { + return nil, trace.Wrap(err) + } } // Create the clients for the fetcher From da36e405454d3c79d5456ad0aa599a5508b4ab4b Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Thu, 23 Jan 2025 11:06:30 -0600 Subject: [PATCH 44/46] e ref --- e | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e b/e index fe3b9e44eaee9..052b9c2436c85 160000 --- a/e +++ b/e @@ -1 +1 @@ -Subproject commit fe3b9e44eaee95db7dbb527a52ac064b6186e56a +Subproject commit 052b9c2436c8509628889751d88fc5410763cca2 From 31064b09b99b921948718fc27037dc7a2ff1c218 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Thu, 23 Jan 2025 11:33:48 -0600 Subject: [PATCH 45/46] Lint --- lib/srv/discovery/fetchers/azuresync/azure-sync.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/srv/discovery/fetchers/azuresync/azure-sync.go b/lib/srv/discovery/fetchers/azuresync/azure-sync.go index 65c5b6eda56c2..2e19177b11671 100644 --- a/lib/srv/discovery/fetchers/azuresync/azure-sync.go +++ b/lib/srv/discovery/fetchers/azuresync/azure-sync.go @@ -20,12 +20,13 @@ package azuresync import ( "context" - "github.com/gravitational/teleport/api/types" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/gravitational/trace" "golang.org/x/sync/errgroup" + "github.com/gravitational/teleport/api/types" accessgraphv1alpha "github.com/gravitational/teleport/gen/proto/go/accessgraph/v1alpha" "github.com/gravitational/teleport/lib/cloud/azure" "github.com/gravitational/teleport/lib/msgraph" From 696d4aa97eceb372252362068c0246e2320a67c1 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Thu, 23 Jan 2025 11:44:13 -0600 Subject: [PATCH 46/46] Fix imports --- lib/srv/discovery/fetchers/azuresync/azure-sync.go | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/srv/discovery/fetchers/azuresync/azure-sync.go b/lib/srv/discovery/fetchers/azuresync/azure-sync.go index 2e19177b11671..3f00071c9e679 100644 --- a/lib/srv/discovery/fetchers/azuresync/azure-sync.go +++ b/lib/srv/discovery/fetchers/azuresync/azure-sync.go @@ -21,7 +21,6 @@ package azuresync import ( "context" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/gravitational/trace" "golang.org/x/sync/errgroup"