Skip to content

Commit

Permalink
AWS console access (#7590)
Browse files Browse the repository at this point in the history
  • Loading branch information
r0mant authored Jul 26, 2021
1 parent 7bc95b7 commit 1576833
Show file tree
Hide file tree
Showing 29 changed files with 1,946 additions and 926 deletions.
1 change: 1 addition & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,7 @@ func (c *Client) CreateAppSession(ctx context.Context, req types.CreateAppSessio
Username: req.Username,
PublicAddr: req.PublicAddr,
ClusterName: req.ClusterName,
AWSRoleARN: req.AWSRoleARN,
}, c.callOpts...)
if err != nil {
return nil, trail.FromGRPC(err)
Expand Down
809 changes: 431 additions & 378 deletions api/client/proto/authservice.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions api/client/proto/authservice.proto
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ message CreateAppSessionRequest {
string PublicAddr = 3 [ (gogoproto.jsontag) = "public_addr" ];
// ClusterName is cluster within which the application is running.
string ClusterName = 4 [ (gogoproto.jsontag) = "cluster_name" ];
// AWSRoleARN is AWS role the user wants to assume.
string AWSRoleARN = 5 [ (gogoproto.jsontag) = "aws_role_arn" ];
}

// CreateAppSessionResponse contains the requested application web session.
Expand Down
5 changes: 5 additions & 0 deletions api/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ const (
//
// TODO(r0mant): See if we can use net.ErrClosed and errors.Is() instead.
UseOfClosedNetworkConnection = "use of closed network connection"

// AWSConsoleURL is the URL of AWS management console.
AWSConsoleURL = "https://console.aws.amazon.com"
// AWSAccountIDLabel is the key of the label containing AWS account ID.
AWSAccountIDLabel = "aws_account_id"
)

// SecondFactorType is the type of 2FA authentication.
Expand Down
611 changes: 329 additions & 282 deletions api/types/events/events.pb.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions api/types/events/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ message UserMetadata {

// Impersonator is a user acting on behalf of another user
string Impersonator = 3 [ (gogoproto.jsontag) = "impersonator,omitempty" ];

// AWSRoleARN is AWS IAM role user assumes when accessing AWS console.
string AWSRoleARN = 4 [ (gogoproto.jsontag) = "aws_role_arn,omitempty" ];
}

// Server is a server metadata
Expand Down
27 changes: 27 additions & 0 deletions api/types/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ type Role interface {
GetImpersonateConditions(rct RoleConditionType) ImpersonateConditions
// SetImpersonateConditions returns conditions this role is allowed or denied to impersonate.
SetImpersonateConditions(rct RoleConditionType, cond ImpersonateConditions)

// GetAWSRoleARNs returns a list of AWS role ARNs this role is allowed to assume.
GetAWSRoleARNs(RoleConditionType) []string
// SetAWSRoleARNs returns a list of AWS role ARNs this role is allowed to assume.
SetAWSRoleARNs(RoleConditionType, []string)
}

// NewRole constructs new standard role
Expand Down Expand Up @@ -465,6 +470,23 @@ func (r *RoleV4) SetImpersonateConditions(rct RoleConditionType, cond Impersonat
}
}

// GetAWSRoleARNs returns a list of AWS role ARNs this role is allowed to impersonate.
func (r *RoleV4) GetAWSRoleARNs(rct RoleConditionType) []string {
if rct == Allow {
return r.Spec.Allow.AWSRoleARNs
}
return r.Spec.Deny.AWSRoleARNs
}

// SetAWSRoleARNs sets a list of AWS role ARNs this role is allowed to impersonate.
func (r *RoleV4) SetAWSRoleARNs(rct RoleConditionType, arns []string) {
if rct == Allow {
r.Spec.Allow.AWSRoleARNs = arns
} else {
r.Spec.Deny.AWSRoleARNs = arns
}
}

// GetRules gets all allow or deny rules.
func (r *RoleV4) GetRules(rct RoleConditionType) []Rule {
if rct == Allow {
Expand Down Expand Up @@ -572,6 +594,11 @@ func (r *RoleV4) CheckAndSetDefaults() error {
return trace.BadParameter("wildcard matcher is not allowed in logins")
}
}
for _, arn := range r.Spec.Allow.AWSRoleARNs {
if arn == Wildcard {
return trace.BadParameter("wildcard matcher is not allowed in aws_role_arns")
}
}
for key, val := range r.Spec.Allow.NodeLabels {
if key == Wildcard && !(len(val) == 1 && val[0] == Wildcard) {
return trace.BadParameter("selector *:<val> is not supported")
Expand Down
12 changes: 12 additions & 0 deletions api/types/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"strings"
"time"

"github.com/gravitational/teleport/api/constants"

"github.com/gogo/protobuf/proto"
"github.com/gravitational/trace"
)
Expand Down Expand Up @@ -354,6 +356,16 @@ func (s *ServerV2) DeepCopy() Server {
return proto.Clone(s).(*ServerV2)
}

// IsAWSConsole returns true if this app is AWS management console.
func (a *App) IsAWSConsole() bool {
return strings.HasPrefix(a.URI, constants.AWSConsoleURL)
}

// GetAWSAccountID returns value of label containing AWS account ID on this app.
func (a *App) GetAWSAccountID() string {
return a.StaticLabels[constants.AWSAccountIDLabel]
}

// CommandLabel is a label that has a value as a result of the
// output generated by running command, e.g. hostname
type CommandLabel interface {
Expand Down
2 changes: 2 additions & 0 deletions api/types/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ type CreateAppSessionRequest struct {
PublicAddr string `json:"public_addr"`
// ClusterName is the name of the cluster within which the application is running.
ClusterName string `json:"cluster_name"`
// AWSRoleARN is AWS role this the user wants to assume.
AWSRoleARN string `json:"aws_role_arn"`
}

// Check validates the request.
Expand Down
Loading

0 comments on commit 1576833

Please sign in to comment.