Files
teleport/lib/join/server_iam.go
T
rosstimothy 4f17314a11 Initial migration to the Opaque API (#67279)
* Convert existing non-gogo codegen to the Hybrid API

Contributes to https://github.com/gravitational/teleport/issues/66776.

All existing protos explicitly set to API_OPEN have been change to
API_HBYRID. The new codegen was performed via make grpc. There are no
other functional changes to the code to start consuming the Hybrid API
those will come later. The intent is to get all Hybrid codegen in and
backported to ease the transition.

* Initial migration to the Opaque API

Contributes to https://github.com/gravitational/teleport/issues/66776.

All of the changes here are mechanical conversions generated from
`open2opaque rewrite -levels=green ./...`. There will be a follow up
to this in teleport.e which does the same. Once all changes have been
merged the process will be repeated with -levels=yellow followed by
-levels=red.


See https://protobuf.dev/reference/go/opaque-migration/ for more
details.
2026-06-05 14:52:58 +00:00

112 lines
4.0 KiB
Go

// Teleport
// Copyright (C) 2025 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package join
import (
"github.com/gravitational/trace"
workloadidentityv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/workloadidentity/v1"
"github.com/gravitational/teleport/lib/join/iamjoin"
"github.com/gravitational/teleport/lib/join/internal/authz"
"github.com/gravitational/teleport/lib/join/internal/diagnostic"
"github.com/gravitational/teleport/lib/join/internal/messages"
"github.com/gravitational/teleport/lib/join/provision"
)
// handleIAMJoin handles join attempts for the IAM join method.
//
// The IAM join method involves the following messages:
//
// client->server ClientInit
// client<-server ServerInit
// client->server IAMInit
// client<-server IAMChallenge
// client->server IAMChallengeSolution
// client<-server Result
//
// At this point the ServerInit message has already been sent, what's left is
// to receive the IAMInit message, handle the challenge-response, and send the
// final result if everything checks out.
func (s *Server) handleIAMJoin(
stream messages.ServerStream,
authCtx *authz.Context,
clientInit *messages.ClientInit,
token provision.Token,
) (messages.Response, error) {
// Receive the IAMInit message from the client.
iamInit, err := messages.RecvRequest[*messages.IAMInit](stream)
if err != nil {
return nil, trace.Wrap(err, "receiving IAMInit message")
}
// Set any diagnostic info from the ClientParams.
setDiagnosticClientParams(stream.Diagnostic(), &iamInit.ClientParams)
// Generate and send the challenge.
challenge, err := iamjoin.GenerateIAMChallenge()
if err != nil {
return nil, trace.Wrap(err, "generating challenge")
}
if err := stream.Send(&messages.IAMChallenge{
Challenge: challenge,
}); err != nil {
return nil, trace.Wrap(err, "sending challenge")
}
// Receive the solution from the client.
solution, err := messages.RecvRequest[*messages.IAMChallengeSolution](stream)
if err != nil {
return nil, trace.Wrap(err, "receiving challenge solution")
}
// Verify the sts:GetCallerIdentity request, send it to AWS, and make sure
// the verified identity matches allow rules in the provision token.
verifiedIdentity, err := iamjoin.CheckIAMRequest(stream.Context(), &iamjoin.CheckIAMRequestParams{
Logger: s.cfg.Logger,
Challenge: challenge,
ProvisionToken: token,
STSIdentityRequest: solution.STSIdentityRequest,
HTTPClient: s.cfg.AuthService.GetHTTPClientForAWSSTS(),
FIPS: s.cfg.FIPS,
OrganizationsAPIGetter: s.cfg.AuthService.GetAWSOrganizationsClientGetter(),
AWSOIDCIntegrationClient: s.cfg.AuthService,
})
// An identity will be returned even on error if the sts:GetCallerIdentity
// request was completed but no allow rules were matched, include it in the
// diagnostic for debugging.
stream.Diagnostic().Set(func(info *diagnostic.Info) {
info.RawJoinAttrs = verifiedIdentity
})
if err != nil {
return nil, trace.Wrap(err, "verifying challenge response")
}
// Make and return the final result message.
result, err := s.makeResult(
stream.Context(),
stream.Diagnostic(),
authCtx,
clientInit,
&iamInit.ClientParams,
token,
verifiedIdentity,
workloadidentityv1pb.JoinAttrs_builder{
Iam: verifiedIdentity.JoinAttrs(),
}.Build(),
)
return result, trace.Wrap(err)
}