Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4054,8 +4054,10 @@ func (c *Client) DeleteAllIntegrations(ctx context.Context) error {
}

// GenerateAWSOIDCToken generates a token to be used when executing an AWS OIDC Integration action.
func (c *Client) GenerateAWSOIDCToken(ctx context.Context) (string, error) {
resp, err := c.integrationsClient().GenerateAWSOIDCToken(ctx, &integrationpb.GenerateAWSOIDCTokenRequest{})
func (c *Client) GenerateAWSOIDCToken(ctx context.Context, integration string) (string, error) {
resp, err := c.integrationsClient().GenerateAWSOIDCToken(ctx, &integrationpb.GenerateAWSOIDCTokenRequest{
Integration: integration,
})
if err != nil {
return "", trace.Wrap(err)
}
Expand Down
109 changes: 61 additions & 48 deletions api/gen/proto/go/teleport/integration/v1/integration_service.pb.go

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

5 changes: 5 additions & 0 deletions api/proto/teleport/integration/v1/integration_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ message GenerateAWSOIDCTokenRequest {
//
// Deprecated: Ignored because value is calculated server side.
string issuer = 1 [deprecated = true];

// Integration is the AWS OIDC Integration name.
// If not provided, it will use the Teleport's Proxy Public URL as issuer.
// Optional.
string integration = 2;
}

// GenerateAWSOIDCTokenResponse contains a signed AWS OIDC Integration token.
Expand Down
8 changes: 8 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6150,6 +6150,14 @@ message AWSOIDCIntegrationSpecV1 {
// RoleARN contains the Role ARN used to set up the Integration.
// This is the AWS Role that Teleport will use to issue tokens for API Calls.
string RoleARN = 1 [(gogoproto.jsontag) = "role_arn,omitempty"];

// IssuerS3URI is the Identity Provider that was configured in AWS.
// This bucket/prefix/* files must be publicly accessible and contain the following:
// > .well-known/openid-configuration
// > .well-known/jwks
// Format: s3://<bucket>/<prefix>
// Optional. The proxy's endpoint is used if it is not specified.
string IssuerS3URI = 2 [(gogoproto.jsontag) = "issuer_s3_uri,omitempty"];
}

// HeadlessAuthentication holds data for an ongoing headless authentication attempt.
Expand Down
29 changes: 29 additions & 0 deletions api/types/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package types
import (
"encoding/json"
"fmt"
"net/url"

"github.com/gravitational/trace"

Expand All @@ -43,6 +44,9 @@ type Integration interface {
SetAWSOIDCIntegrationSpec(*AWSOIDCIntegrationSpecV1)
// SetAWSOIDCRoleARN sets the RoleARN of the AWS OIDC Spec.
SetAWSOIDCRoleARN(string)
// SetAWSOIDCIssuerS3URI sets the IssuerS3URI of the AWS OIDC Spec.
// Eg, s3://my-bucket/my-prefix
SetAWSOIDCIssuerS3URI(string)
}

var _ ResourceWithLabels = (*IntegrationV1)(nil)
Expand Down Expand Up @@ -139,6 +143,18 @@ func (s *IntegrationSpecV1_AWSOIDC) CheckAndSetDefaults() error {
return trace.BadParameter("role_arn is required for %q subkind", IntegrationSubKindAWSOIDC)
}

// The Issuer can be empty.
// In that case it will use the cluster's web endpoint.
if s.AWSOIDC.IssuerS3URI != "" {
issuerS3URL, err := url.Parse(s.AWSOIDC.IssuerS3URI)
if err != nil {
return trace.BadParameter("unable to parse issuer s3 uri, valid format (eg, s3://my-bucket/my-prefix)")
}
if issuerS3URL.Scheme != "s3" || issuerS3URL.Host == "" || issuerS3URL.Path == "" {
return trace.BadParameter("issuer s3 uri must be in a valid format (eg, s3://my-bucket/my-prefix)")
}
}

return nil
}

Expand Down Expand Up @@ -167,6 +183,19 @@ func (ig *IntegrationV1) SetAWSOIDCRoleARN(roleARN string) {
}
}

// SetAWSOIDCIssuer sets the Issuer of the AWS OIDC Spec.
func (ig *IntegrationV1) SetAWSOIDCIssuerS3URI(issuerS3URI string) {
currentSubSpec := ig.Spec.GetAWSOIDC()
if currentSubSpec == nil {
currentSubSpec = &AWSOIDCIntegrationSpecV1{}
}

currentSubSpec.IssuerS3URI = issuerS3URI
ig.Spec.SubKindSpec = &IntegrationSpecV1_AWSOIDC{
AWSOIDC: currentSubSpec,
}
}

// Integrations is a list of Integration resources.
type Integrations []Integration

Expand Down
43 changes: 40 additions & 3 deletions api/types/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ func TestIntegrationJSONMarshalCycle(t *testing.T) {
ig, err := NewIntegrationAWSOIDC(
Metadata{Name: "some-integration"},
&AWSOIDCIntegrationSpecV1{
RoleARN: "arn:aws:iam::123456789012:role/DevTeams",
RoleARN: "arn:aws:iam::123456789012:role/DevTeams",
IssuerS3URI: "s3://my-bucket/my-prefix",
},
)
require.NoError(t, err)
Expand Down Expand Up @@ -65,7 +66,8 @@ func TestIntegrationCheckAndSetDefaults(t *testing.T) {
Name: name,
},
&AWSOIDCIntegrationSpecV1{
RoleARN: "some arn role",
RoleARN: "some arn role",
IssuerS3URI: "s3://my-issuer/my-prefix",
},
)
},
Expand All @@ -83,7 +85,8 @@ func TestIntegrationCheckAndSetDefaults(t *testing.T) {
Spec: IntegrationSpecV1{
SubKindSpec: &IntegrationSpecV1_AWSOIDC{
AWSOIDC: &AWSOIDCIntegrationSpecV1{
RoleARN: "some arn role",
RoleARN: "some arn role",
IssuerS3URI: "s3://my-issuer/my-prefix",
},
},
},
Expand All @@ -105,6 +108,40 @@ func TestIntegrationCheckAndSetDefaults(t *testing.T) {
return trace.IsBadParameter(err)
},
},
{
name: "aws-oidc: error when issuer is not a valid url",
integration: func(name string) (*IntegrationV1, error) {
return NewIntegrationAWSOIDC(
Metadata{
Name: name,
},
&AWSOIDCIntegrationSpecV1{
RoleARN: "some-role",
IssuerS3URI: "not-a-url",
},
)
},
expectedErrorIs: func(err error) bool {
return trace.IsBadParameter(err)
},
},
{
name: "aws-oidc: issuer is not an s3 url",
integration: func(name string) (*IntegrationV1, error) {
return NewIntegrationAWSOIDC(
Metadata{
Name: name,
},
&AWSOIDCIntegrationSpecV1{
RoleARN: "some-role",
IssuerS3URI: "http://localhost:8080",
},
)
},
expectedErrorIs: func(err error) bool {
return trace.IsBadParameter(err)
},
},
{
name: "aws-oidc: error when no role is provided",
integration: func(name string) (*IntegrationV1, error) {
Expand Down
Loading