mirror of
https://github.com/gravitational/teleport
synced 2024-10-19 08:43:58 +00:00
This reverts commit 3fba50261f
.
This commit is contained in:
parent
791f97eba7
commit
eb42cabbea
|
@ -1964,58 +1964,25 @@ func (c *Client) DeleteTrustedCluster(ctx context.Context, name string) error {
|
|||
return trail.FromGRPC(err)
|
||||
}
|
||||
|
||||
// DELETE IN 13.0 (strideynet)
|
||||
func (c *Client) getTokenV2(ctx context.Context, name string) (types.ProvisionToken, error) {
|
||||
//nolint:staticcheck // SA1019 Deprecated call will be removed in 13.0
|
||||
resp, err := c.grpc.GetToken(ctx, &types.ResourceRequest{Name: name}, c.callOpts...)
|
||||
if err != nil {
|
||||
return nil, trail.FromGRPC(err)
|
||||
}
|
||||
return resp.V3(), nil
|
||||
}
|
||||
|
||||
// GetToken returns a provision token by name.
|
||||
func (c *Client) GetToken(ctx context.Context, name string) (types.ProvisionToken, error) {
|
||||
if name == "" {
|
||||
return nil, trace.BadParameter("cannot get token, missing name")
|
||||
}
|
||||
resp, err := c.grpc.GetTokenV3(ctx, &types.ResourceRequest{Name: name}, c.callOpts...)
|
||||
resp, err := c.grpc.GetToken(ctx, &types.ResourceRequest{Name: name}, c.callOpts...)
|
||||
if err != nil {
|
||||
err = trail.FromGRPC(err)
|
||||
if trace.IsNotImplemented(err) {
|
||||
return c.getTokenV2(ctx, name)
|
||||
}
|
||||
return nil, err
|
||||
return nil, trail.FromGRPC(err)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DELETE IN 13.0 (strideynet)
|
||||
func (c *Client) getTokensV2(ctx context.Context) ([]types.ProvisionToken, error) {
|
||||
//nolint:staticcheck // SA1019 Deprecated call will be removed in 13.0
|
||||
// GetTokens returns a list of active provision tokens for nodes and users.
|
||||
func (c *Client) GetTokens(ctx context.Context) ([]types.ProvisionToken, error) {
|
||||
resp, err := c.grpc.GetTokens(ctx, &emptypb.Empty{}, c.callOpts...)
|
||||
if err != nil {
|
||||
return nil, trail.FromGRPC(err)
|
||||
}
|
||||
|
||||
tokens := make([]types.ProvisionToken, len(resp.ProvisionTokens))
|
||||
for i, token := range resp.ProvisionTokens {
|
||||
tokens[i] = token.V3()
|
||||
}
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
// GetTokens returns a list of active provision tokens for nodes and users.
|
||||
func (c *Client) GetTokens(ctx context.Context) ([]types.ProvisionToken, error) {
|
||||
resp, err := c.grpc.GetTokensV3(ctx, &emptypb.Empty{}, c.callOpts...)
|
||||
if err != nil {
|
||||
err = trail.FromGRPC(err)
|
||||
if trace.IsNotImplemented(err) {
|
||||
return c.getTokensV2(ctx)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tokens := make([]types.ProvisionToken, len(resp.ProvisionTokens))
|
||||
for i, token := range resp.ProvisionTokens {
|
||||
tokens[i] = token
|
||||
|
@ -2025,13 +1992,21 @@ func (c *Client) GetTokens(ctx context.Context) ([]types.ProvisionToken, error)
|
|||
|
||||
// UpsertToken creates or updates a provision token.
|
||||
func (c *Client) UpsertToken(ctx context.Context, token types.ProvisionToken) error {
|
||||
_, err := c.grpc.UpsertTokenV3(ctx, token.V3(), c.callOpts...)
|
||||
tokenV2, ok := token.(*types.ProvisionTokenV2)
|
||||
if !ok {
|
||||
return trace.BadParameter("invalid type %T", token)
|
||||
}
|
||||
_, err := c.grpc.UpsertToken(ctx, tokenV2, c.callOpts...)
|
||||
return trail.FromGRPC(err)
|
||||
}
|
||||
|
||||
// CreateToken creates a provision token.
|
||||
func (c *Client) CreateToken(ctx context.Context, token types.ProvisionToken) error {
|
||||
_, err := c.grpc.CreateTokenV3(ctx, token.V3(), c.callOpts...)
|
||||
tokenV2, ok := token.(*types.ProvisionTokenV2)
|
||||
if !ok {
|
||||
return trace.BadParameter("invalid type %T", token)
|
||||
}
|
||||
_, err := c.grpc.CreateToken(ctx, tokenV2, c.callOpts...)
|
||||
return trail.FromGRPC(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -45,9 +45,9 @@ func EventToGRPC(in types.Event) (*proto.Event, error) {
|
|||
out.Resource = &proto.Event_StaticTokens{
|
||||
StaticTokens: r,
|
||||
}
|
||||
case *types.ProvisionTokenV3:
|
||||
out.Resource = &proto.Event_ProvisionTokenV3{
|
||||
ProvisionTokenV3: r,
|
||||
case *types.ProvisionTokenV2:
|
||||
out.Resource = &proto.Event_ProvisionToken{
|
||||
ProvisionToken: r,
|
||||
}
|
||||
case *types.ClusterNameV2:
|
||||
out.Resource = &proto.Event_ClusterName{
|
||||
|
@ -207,7 +207,7 @@ func EventFromGRPC(in proto.Event) (*types.Event, error) {
|
|||
} else if r := in.GetStaticTokens(); r != nil {
|
||||
out.Resource = r
|
||||
return &out, nil
|
||||
} else if r := in.GetProvisionTokenV3(); r != nil {
|
||||
} else if r := in.GetProvisionToken(); r != nil {
|
||||
out.Resource = r
|
||||
return &out, nil
|
||||
} else if r := in.GetClusterName(); r != nil {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -115,8 +115,6 @@ message Event {
|
|||
types.KubernetesClusterV3 KubernetesCluster = 33 [(gogoproto.jsontag) = "kubernetes_cluster,omitempty"];
|
||||
// Installer is an installer resource
|
||||
types.InstallerV1 Installer = 34 [(gogoproto.jsontag) = "installer,omitempty"];
|
||||
// ProvisionTokenV3 is a V3 Provision Token resource.
|
||||
types.ProvisionTokenV3 ProvisionTokenV3 = 35 [(gogoproto.jsontag) = "provision_token_v3,omitempty"];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2429,30 +2427,14 @@ service AuthService {
|
|||
// DeleteTrustedCluster deletes an existing Trusted Cluster in a backend by name.
|
||||
rpc DeleteTrustedCluster(types.ResourceRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// GetToken retrieves a v2 token described by the given request.
|
||||
// Deprecated: use GetTokenV3.
|
||||
// DELETE IN 13.0 (strideynet).
|
||||
// GetToken retrieves a token described by the given request.
|
||||
rpc GetToken(types.ResourceRequest) returns (types.ProvisionTokenV2);
|
||||
// GetTokenV3 retrieves a token described by the given request.
|
||||
rpc GetTokenV3(types.ResourceRequest) returns (types.ProvisionTokenV3);
|
||||
// GetTokens retrieves all v2 tokens.
|
||||
// Deprecated: use GetTokensV3.
|
||||
// DELETE IN 13.0 (strideynet).
|
||||
// GetToken retrieves all tokens.
|
||||
rpc GetTokens(google.protobuf.Empty) returns (types.ProvisionTokenV2List);
|
||||
// GetTokensV3 retrieves all tokens.
|
||||
rpc GetTokensV3(google.protobuf.Empty) returns (types.ProvisionTokenV3List);
|
||||
// UpsertToken upserts a v2 token in a backend.
|
||||
// Deprecated: use UpsertTokenV3.
|
||||
// DELETE IN 13.0 (strideynet).
|
||||
// UpsertToken upserts a token in a backend.
|
||||
rpc UpsertToken(types.ProvisionTokenV2) returns (google.protobuf.Empty);
|
||||
// UpsertTokenV3 upserts a v3 token in a backend.
|
||||
rpc UpsertTokenV3(types.ProvisionTokenV3) returns (google.protobuf.Empty);
|
||||
// CreateToken creates a v2 token in a backend.
|
||||
// Deprecated: Use CreateTokenV3.
|
||||
// DELETE IN 13.0 (strideynet)
|
||||
// CreateToken creates a token in a backend.
|
||||
rpc CreateToken(types.ProvisionTokenV2) returns (google.protobuf.Empty);
|
||||
// CreateTokenV3 creates a v3 token in a backend.
|
||||
rpc CreateTokenV3(types.ProvisionTokenV3) returns (google.protobuf.Empty);
|
||||
// GenerateToken generates a new auth token.
|
||||
rpc GenerateToken(GenerateTokenRequest) returns (GenerateTokenResponse);
|
||||
// DeleteToken deletes an existing token in a backend described by the given request.
|
||||
|
|
|
@ -963,103 +963,6 @@ message ProvisionTokenSpecV2 {
|
|||
];
|
||||
}
|
||||
|
||||
// ProvisionTokenV3 specifies provisioning token
|
||||
message ProvisionTokenV3 {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
option (gogoproto.stringer) = false;
|
||||
|
||||
// Kind is a resource kind
|
||||
string Kind = 1 [(gogoproto.jsontag) = "kind"];
|
||||
// SubKind is an optional resource sub kind, used in some resources
|
||||
string SubKind = 2 [(gogoproto.jsontag) = "sub_kind,omitempty"];
|
||||
// Version is version
|
||||
string Version = 3 [(gogoproto.jsontag) = "version"];
|
||||
// Metadata is resource metadata
|
||||
Metadata Metadata = 4 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.jsontag) = "metadata"
|
||||
];
|
||||
// Spec is a provisioning token V3 spec
|
||||
ProvisionTokenSpecV3 Spec = 5 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.jsontag) = "spec"
|
||||
];
|
||||
}
|
||||
|
||||
// ProvisionTokenV3List is a list of provisioning tokens.
|
||||
message ProvisionTokenV3List {
|
||||
// ProvisionTokens is a list of provisioning tokens.
|
||||
repeated ProvisionTokenV3 ProvisionTokens = 1;
|
||||
}
|
||||
|
||||
message ProvisionTokenSpecV3 {
|
||||
// Roles is a list of roles associated with the token, that will be converted
|
||||
// to metadata in the SSH and X509 certificates issued to the user of the
|
||||
// token.
|
||||
repeated string Roles = 1 [
|
||||
(gogoproto.jsontag) = "roles",
|
||||
(gogoproto.casttype) = "SystemRole"
|
||||
];
|
||||
// JoinMethod is the joining method required in order to use this token.
|
||||
// Supported joining methods include:
|
||||
// - "token"
|
||||
// - "ec2"
|
||||
// - "iam"
|
||||
string JoinMethod = 2 [
|
||||
(gogoproto.jsontag) = "join_method",
|
||||
(gogoproto.casttype) = "JoinMethod"
|
||||
];
|
||||
// BotName is the name of the bot this token grants access to.
|
||||
// This field must be set if the token includes the `Bot` role. It cannot be
|
||||
// set if the token does not include this role.
|
||||
string BotName = 3 [(gogoproto.jsontag) = "bot_name,omitempty"];
|
||||
// SuggestedLabels is a set of labels that resources should set when using
|
||||
// this token to enroll themselves in the cluster.
|
||||
wrappers.LabelValues SuggestedLabels = 4 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.jsontag) = "suggested_labels,omitempty",
|
||||
(gogoproto.customtype) = "Labels"
|
||||
];
|
||||
// IAM allows the configuration of options specific to the "iam" join method.
|
||||
ProvisionTokenSpecV3AWSIAM IAM = 5 [(gogoproto.jsontag) = "aws_iam,omitempty"];
|
||||
// EC2 allows the configuration of options specific to the "ec2" join method.
|
||||
ProvisionTokenSpecV3AWSEC2 EC2 = 6 [(gogoproto.jsontag) = "aws_ec2,omitempty"];
|
||||
}
|
||||
|
||||
message ProvisionTokenSpecV3AWSEC2 {
|
||||
message Rule {
|
||||
// Account is the AWS account ID.
|
||||
string Account = 1 [(gogoproto.jsontag) = "account,omitempty"];
|
||||
// Regions is a list of AWS regions a node is allowed to join from.
|
||||
repeated string Regions = 2 [(gogoproto.jsontag) = "regions,omitempty"];
|
||||
// Role is the the ARN of the AWS role that the auth server will assume
|
||||
// in order to call the ec2 API.
|
||||
string RoleARN = 3 [(gogoproto.jsontag) = "role_arn,omitempty"];
|
||||
}
|
||||
// Allow is a list of TokenRules, nodes using this token must match one
|
||||
// allow rule to use this token.
|
||||
repeated Rule Allow = 1 [(gogoproto.jsontag) = "allow,omitempty"];
|
||||
// IIDTTL is the TTL to use for AWS EC2 Instance Identity Documents used
|
||||
// to join the cluster with this token.
|
||||
int64 IIDTTL = 2 [
|
||||
(gogoproto.jsontag) = "iid_ttl,omitempty",
|
||||
(gogoproto.casttype) = "Duration"
|
||||
];
|
||||
}
|
||||
|
||||
message ProvisionTokenSpecV3AWSIAM {
|
||||
message Rule {
|
||||
// Account is the AWS account ID.
|
||||
string Account = 1 [(gogoproto.jsontag) = "account,omitempty"];
|
||||
// ARN is used for the IAM join method, the AWS identity of joining nodes
|
||||
// must match this ARN. Supports wildcards "*" and "?".
|
||||
string ARN = 2 [(gogoproto.jsontag) = "arn,omitempty"];
|
||||
}
|
||||
// Allow is a list of TokenRules, nodes using this token must match one
|
||||
// allow rule to use this token.
|
||||
repeated Rule Allow = 1 [(gogoproto.jsontag) = "allow,omitempty"];
|
||||
}
|
||||
|
||||
// StaticTokensV2 implements the StaticTokens interface.
|
||||
message StaticTokensV2 {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
|
@ -1069,7 +972,7 @@ message StaticTokensV2 {
|
|||
string Kind = 1 [(gogoproto.jsontag) = "kind"];
|
||||
// SubKind is an optional resource sub kind, used in some resources
|
||||
string SubKind = 2 [(gogoproto.jsontag) = "sub_kind,omitempty"];
|
||||
// Version is the version of the resource kind
|
||||
// Version is version
|
||||
string Version = 3 [(gogoproto.jsontag) = "version"];
|
||||
// Metadata is resource metadata
|
||||
Metadata Metadata = 4 [
|
||||
|
|
|
@ -288,10 +288,6 @@ const (
|
|||
// V1 is the first version of resources. Note: The first version was
|
||||
// not explicitly versioned.
|
||||
V1 = "v1"
|
||||
|
||||
// VDeleted indicates that the version information for this resource
|
||||
// cannot be determined as it is being included as part of a delete Event.
|
||||
VDeleted = "deleted"
|
||||
)
|
||||
|
||||
// WebSessionSubKinds lists subkinds of web session resources
|
||||
|
|
|
@ -78,33 +78,22 @@ type ProvisionToken interface {
|
|||
// GetSuggestedLabels returns the set of labels that the resource should add when adding itself to the cluster
|
||||
GetSuggestedLabels() Labels
|
||||
|
||||
// V1 returns V1 version of the resource
|
||||
V1() *ProvisionTokenV1
|
||||
// String returns user friendly representation of the resource
|
||||
String() string
|
||||
|
||||
// V3 returns the V3 representation of a ProvisionToken. This can be used
|
||||
// for conversion to a concrete type in preparation for serialization into
|
||||
// a rpc message.
|
||||
V3() *ProvisionTokenV3
|
||||
|
||||
// V2 returns the V2 representation of a ProvisionToken
|
||||
// This exists for the transition period where the V2 Token RPCs still exist
|
||||
// and we may need to be able to convert V3 tokens to a V2 representation
|
||||
// for serialization.
|
||||
// DELETE IN 13.0 (strideynet)
|
||||
V2() (*ProvisionTokenV2, error)
|
||||
}
|
||||
|
||||
// NewProvisionToken returns a new provision token with the given roles.
|
||||
func NewProvisionToken(token string, roles SystemRoles, expires time.Time) (ProvisionToken, error) {
|
||||
return NewProvisionTokenFromSpec(token, expires, ProvisionTokenSpecV3{
|
||||
JoinMethod: JoinMethodToken,
|
||||
Roles: roles,
|
||||
return NewProvisionTokenFromSpec(token, expires, ProvisionTokenSpecV2{
|
||||
Roles: roles,
|
||||
})
|
||||
}
|
||||
|
||||
// NewProvisionTokenFromSpec returns a new provision token with the given spec.
|
||||
func NewProvisionTokenFromSpec(token string, expires time.Time, spec ProvisionTokenSpecV3) (ProvisionToken, error) {
|
||||
t := &ProvisionTokenV3{
|
||||
func NewProvisionTokenFromSpec(token string, expires time.Time, spec ProvisionTokenSpecV2) (ProvisionToken, error) {
|
||||
t := &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: token,
|
||||
Expires: &expires,
|
||||
|
@ -117,8 +106,44 @@ func NewProvisionTokenFromSpec(token string, expires time.Time, spec ProvisionTo
|
|||
return t, nil
|
||||
}
|
||||
|
||||
// V3 returns V3 version of the ProvisionTokenV2 resource.
|
||||
func (p *ProvisionTokenV2) V3() *ProvisionTokenV3 {
|
||||
// MustCreateProvisionToken returns a new valid provision token
|
||||
// or panics, used in tests
|
||||
func MustCreateProvisionToken(token string, roles SystemRoles, expires time.Time) ProvisionToken {
|
||||
t, err := NewProvisionToken(token, roles, expires)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// setStaticFields sets static resource header and metadata fields.
|
||||
func (p *ProvisionTokenV2) setStaticFields() {
|
||||
p.Kind = KindToken
|
||||
p.Version = V2
|
||||
}
|
||||
|
||||
// CheckAndSetDefaults checks and set default values for any missing fields.
|
||||
func (p *ProvisionTokenV2) CheckAndSetDefaults() error {
|
||||
p.setStaticFields()
|
||||
if err := p.Metadata.CheckAndSetDefaults(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
if len(p.Spec.Roles) == 0 {
|
||||
return trace.BadParameter("provisioning token is missing roles")
|
||||
}
|
||||
if err := SystemRoles(p.Spec.Roles).Check(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
if SystemRoles(p.Spec.Roles).Include(RoleBot) && p.Spec.BotName == "" {
|
||||
return trace.BadParameter("token with role %q must set bot_name", RoleBot)
|
||||
}
|
||||
|
||||
if p.Spec.BotName != "" && !SystemRoles(p.Spec.Roles).Include(RoleBot) {
|
||||
return trace.BadParameter("can only set bot_name on token with role %q", RoleBot)
|
||||
}
|
||||
|
||||
hasAllowRules := len(p.Spec.Allow) > 0
|
||||
if p.Spec.JoinMethod == JoinMethodUnspecified {
|
||||
// Default to the ec2 join method if any allow rules were specified,
|
||||
|
@ -130,82 +155,209 @@ func (p *ProvisionTokenV2) V3() *ProvisionTokenV3 {
|
|||
p.Spec.JoinMethod = JoinMethodToken
|
||||
}
|
||||
}
|
||||
v3 := &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Metadata: p.Metadata,
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: p.Spec.Roles,
|
||||
JoinMethod: p.Spec.JoinMethod,
|
||||
BotName: p.Spec.BotName,
|
||||
SuggestedLabels: p.Spec.SuggestedLabels,
|
||||
},
|
||||
}
|
||||
// Add provider specific config.
|
||||
switch p.Spec.JoinMethod {
|
||||
case JoinMethodIAM:
|
||||
iam := &ProvisionTokenSpecV3AWSIAM{}
|
||||
for _, rule := range p.Spec.Allow {
|
||||
iam.Allow = append(iam.Allow, &ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
Account: rule.AWSAccount,
|
||||
ARN: rule.AWSARN,
|
||||
})
|
||||
case JoinMethodToken:
|
||||
if hasAllowRules {
|
||||
return trace.BadParameter("allow rules are not compatible with the %q join method", JoinMethodToken)
|
||||
}
|
||||
v3.Spec.IAM = iam
|
||||
case JoinMethodEC2:
|
||||
ec2 := &ProvisionTokenSpecV3AWSEC2{}
|
||||
for _, rule := range p.Spec.Allow {
|
||||
ec2.Allow = append(ec2.Allow, &ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
Account: rule.AWSAccount,
|
||||
RoleARN: rule.AWSRole,
|
||||
Regions: rule.AWSRegions,
|
||||
})
|
||||
if !hasAllowRules {
|
||||
return trace.BadParameter("the %q join method requires defined token allow rules", JoinMethodEC2)
|
||||
}
|
||||
ec2.IIDTTL = p.Spec.AWSIIDTTL
|
||||
v3.Spec.EC2 = ec2
|
||||
for _, allowRule := range p.Spec.Allow {
|
||||
if allowRule.AWSARN != "" {
|
||||
return trace.BadParameter(`the %q join method does not support the "aws_arn" parameter`, JoinMethodEC2)
|
||||
}
|
||||
if allowRule.AWSAccount == "" && allowRule.AWSRole == "" {
|
||||
return trace.BadParameter(`allow rule for %q join method must set "aws_account" or "aws_role"`, JoinMethodEC2)
|
||||
}
|
||||
}
|
||||
if p.Spec.AWSIIDTTL == 0 {
|
||||
// default to 5 minute ttl if unspecified
|
||||
p.Spec.AWSIIDTTL = Duration(5 * time.Minute)
|
||||
}
|
||||
case JoinMethodIAM:
|
||||
if !hasAllowRules {
|
||||
return trace.BadParameter("the %q join method requires defined token allow rules", JoinMethodIAM)
|
||||
}
|
||||
for _, allowRule := range p.Spec.Allow {
|
||||
if allowRule.AWSRole != "" {
|
||||
return trace.BadParameter(`the %q join method does not support the "aws_role" parameter`, JoinMethodIAM)
|
||||
}
|
||||
if len(allowRule.AWSRegions) != 0 {
|
||||
return trace.BadParameter(`the %q join method does not support the "aws_regions" parameter`, JoinMethodIAM)
|
||||
}
|
||||
if allowRule.AWSAccount == "" && allowRule.AWSARN == "" {
|
||||
return trace.BadParameter(`allow rule for %q join method must set "aws_account" or "aws_arn"`, JoinMethodEC2)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return trace.BadParameter("unknown join method %q", p.Spec.JoinMethod)
|
||||
}
|
||||
return v3
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetVersion returns resource version
|
||||
func (p *ProvisionTokenV2) GetVersion() string {
|
||||
return p.Version
|
||||
}
|
||||
|
||||
// GetRoles returns a list of teleport roles
|
||||
// that will be granted to the user of the token
|
||||
// in the crendentials
|
||||
func (p *ProvisionTokenV2) GetRoles() SystemRoles {
|
||||
return p.Spec.Roles
|
||||
}
|
||||
|
||||
// SetRoles sets teleport roles
|
||||
func (p *ProvisionTokenV2) SetRoles(r SystemRoles) {
|
||||
p.Spec.Roles = r
|
||||
}
|
||||
|
||||
// GetAllowRules returns the list of allow rules
|
||||
func (p *ProvisionTokenV2) GetAllowRules() []*TokenRule {
|
||||
return p.Spec.Allow
|
||||
}
|
||||
|
||||
// GetAWSIIDTTL returns the TTL of EC2 IIDs
|
||||
func (p *ProvisionTokenV2) GetAWSIIDTTL() Duration {
|
||||
return p.Spec.AWSIIDTTL
|
||||
}
|
||||
|
||||
// GetJoinMethod returns joining method that must be used with this token.
|
||||
func (p *ProvisionTokenV2) GetJoinMethod() JoinMethod {
|
||||
return p.Spec.JoinMethod
|
||||
}
|
||||
|
||||
// GetBotName returns the BotName field which must be set for joining bots.
|
||||
func (p *ProvisionTokenV2) GetBotName() string {
|
||||
return p.Spec.BotName
|
||||
}
|
||||
|
||||
// GetKind returns resource kind
|
||||
func (p *ProvisionTokenV2) GetKind() string {
|
||||
return p.Kind
|
||||
}
|
||||
|
||||
// GetSubKind returns resource sub kind
|
||||
func (p *ProvisionTokenV2) GetSubKind() string {
|
||||
return p.SubKind
|
||||
}
|
||||
|
||||
// SetSubKind sets resource subkind
|
||||
func (p *ProvisionTokenV2) SetSubKind(s string) {
|
||||
p.SubKind = s
|
||||
}
|
||||
|
||||
// GetResourceID returns resource ID
|
||||
func (p *ProvisionTokenV2) GetResourceID() int64 {
|
||||
return p.Metadata.ID
|
||||
}
|
||||
|
||||
// SetResourceID sets resource ID
|
||||
func (p *ProvisionTokenV2) SetResourceID(id int64) {
|
||||
p.Metadata.ID = id
|
||||
}
|
||||
|
||||
// GetMetadata returns metadata
|
||||
func (p *ProvisionTokenV2) GetMetadata() Metadata {
|
||||
return p.Metadata
|
||||
}
|
||||
|
||||
// SetMetadata sets resource metatada
|
||||
func (p *ProvisionTokenV2) SetMetadata(meta Metadata) {
|
||||
p.Metadata = meta
|
||||
}
|
||||
|
||||
// GetSuggestedLabels returns the labels the resource should set when using this token
|
||||
func (p *ProvisionTokenV2) GetSuggestedLabels() Labels {
|
||||
return p.Spec.SuggestedLabels
|
||||
}
|
||||
|
||||
// V1 returns V1 version of the resource
|
||||
func (p *ProvisionTokenV2) V1() *ProvisionTokenV1 {
|
||||
return &ProvisionTokenV1{
|
||||
Roles: p.Spec.Roles,
|
||||
Expires: p.Metadata.Expiry(),
|
||||
Token: p.Metadata.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// V2 returns V2 version of the resource
|
||||
func (p *ProvisionTokenV2) V2() *ProvisionTokenV2 {
|
||||
return p
|
||||
}
|
||||
|
||||
// SetExpiry sets expiry time for the object
|
||||
func (p *ProvisionTokenV2) SetExpiry(expires time.Time) {
|
||||
p.Metadata.SetExpiry(expires)
|
||||
}
|
||||
|
||||
// Expiry returns object expiry setting
|
||||
func (p *ProvisionTokenV2) Expiry() time.Time {
|
||||
return p.Metadata.Expiry()
|
||||
}
|
||||
|
||||
// GetName returns server name
|
||||
func (p *ProvisionTokenV2) GetName() string {
|
||||
return p.Metadata.Name
|
||||
}
|
||||
|
||||
// SetName sets the name of the TrustedCluster.
|
||||
func (p *ProvisionTokenV2) SetName(e string) {
|
||||
p.Metadata.Name = e
|
||||
}
|
||||
|
||||
// String returns the human readable representation of a provisioning token.
|
||||
func (p ProvisionTokenV2) String() string {
|
||||
expires := "never"
|
||||
if !p.Metadata.Expiry().IsZero() {
|
||||
expires = p.Metadata.Expiry().String()
|
||||
if !p.Expiry().IsZero() {
|
||||
expires = p.Expiry().String()
|
||||
}
|
||||
return fmt.Sprintf("ProvisionToken(Roles=%v, Expires=%v)", p.Spec.Roles, expires)
|
||||
}
|
||||
|
||||
// ProvisionTokensToV1 converts provision tokens to V1 list
|
||||
func ProvisionTokensToV1(in []ProvisionToken) []ProvisionTokenV1 {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := make([]ProvisionTokenV1, len(in))
|
||||
for i := range in {
|
||||
out[i] = *in[i].V1()
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ProvisionTokensFromV1 converts V1 provision tokens to resource list
|
||||
// This exists to allow the ProvisionTokenV1s embedded within the StaticTokens
|
||||
// specification to be converted to something that implements the
|
||||
// ProvisionToken interface, so that they can be used as part of the join
|
||||
// process in the same way that a ProvisionToken can be.
|
||||
func ProvisionTokensFromV1(in []ProvisionTokenV1) []ProvisionToken {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := make([]ProvisionToken, len(in))
|
||||
for i := range in {
|
||||
out[i] = in[i].V3()
|
||||
out[i] = in[i].V2()
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// V3 returns V3 version of the ProvisionTokenV1 resource.
|
||||
// This is handy for converting a ProvisionTokenV1 embedded within a
|
||||
// StaticToken to a ProvisionToken interface implementing type.
|
||||
func (p *ProvisionTokenV1) V3() *ProvisionTokenV3 {
|
||||
t := &ProvisionTokenV3{
|
||||
// V1 returns V1 version of the resource
|
||||
func (p *ProvisionTokenV1) V1() *ProvisionTokenV1 {
|
||||
return p
|
||||
}
|
||||
|
||||
// V2 returns V2 version of the resource
|
||||
func (p *ProvisionTokenV1) V2() *ProvisionTokenV2 {
|
||||
t := &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Version: V2,
|
||||
Metadata: Metadata{
|
||||
Name: p.Token,
|
||||
Namespace: defaults.Namespace,
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: p.Roles,
|
||||
JoinMethod: JoinMethodToken,
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: p.Roles,
|
||||
},
|
||||
}
|
||||
if !p.Expires.IsZero() {
|
||||
|
@ -224,274 +376,3 @@ func (p ProvisionTokenV1) String() string {
|
|||
return fmt.Sprintf("ProvisionToken(Roles=%v, Expires=%v)",
|
||||
p.Roles, expires)
|
||||
}
|
||||
|
||||
// ProvisionTokenV3 methods
|
||||
|
||||
// setStaticFields sets static resource header and metadata fields.
|
||||
func (p *ProvisionTokenV3) setStaticFields() {
|
||||
p.Kind = KindToken
|
||||
p.Version = V3
|
||||
}
|
||||
|
||||
func (p *ProvisionTokenV3) CheckAndSetDefaults() error {
|
||||
p.setStaticFields()
|
||||
if err := p.Metadata.CheckAndSetDefaults(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
if len(p.Spec.Roles) == 0 {
|
||||
return trace.BadParameter("provisioning token is missing roles")
|
||||
}
|
||||
if err := SystemRoles(p.Spec.Roles).Check(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
if p.Spec.BotName == "" && SystemRoles(p.Spec.Roles).Include(RoleBot) {
|
||||
return trace.BadParameter("token with role %q must set bot_name", RoleBot)
|
||||
} else if p.Spec.BotName != "" && !SystemRoles(p.Spec.Roles).Include(RoleBot) {
|
||||
return trace.BadParameter("can only set bot_name on token with role %q", RoleBot)
|
||||
}
|
||||
|
||||
switch p.Spec.JoinMethod {
|
||||
case JoinMethodIAM:
|
||||
providerCfg := p.Spec.IAM
|
||||
if providerCfg == nil {
|
||||
return trace.BadParameter(
|
||||
`"aws_iam" configuration must be provided for join method %q`,
|
||||
JoinMethodIAM,
|
||||
)
|
||||
}
|
||||
if err := providerCfg.checkAndSetDefaults(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
case JoinMethodEC2:
|
||||
providerCfg := p.Spec.EC2
|
||||
if providerCfg == nil {
|
||||
return trace.BadParameter(
|
||||
`"aws_ec2" configuration must be provided for join method %q`,
|
||||
JoinMethodIAM,
|
||||
)
|
||||
}
|
||||
if err := providerCfg.checkAndSetDefaults(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
case JoinMethodToken:
|
||||
case "":
|
||||
return trace.BadParameter(`"join_method" must be specified`)
|
||||
default:
|
||||
return trace.BadParameter(`join method %q not recognized. check documentation for valid values.`, p.Spec.JoinMethod)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAllowRules returns the list of allow rules.
|
||||
func (p *ProvisionTokenV3) GetAllowRules() []*TokenRule {
|
||||
// For now, we convert the V3 rules to V2 rules, to allow the auth server
|
||||
// implementation to remain the same with the introduction of V3.
|
||||
// GCP OIDC PR will swap the auth server to use the V3 rules and this
|
||||
// method will be gotten ridden of.
|
||||
rules := []*TokenRule{}
|
||||
switch p.Spec.JoinMethod {
|
||||
case JoinMethodIAM:
|
||||
for _, rule := range p.Spec.IAM.Allow {
|
||||
rules = append(rules, &TokenRule{
|
||||
AWSAccount: rule.Account,
|
||||
AWSARN: rule.ARN,
|
||||
})
|
||||
}
|
||||
case JoinMethodEC2:
|
||||
for _, rule := range p.Spec.EC2.Allow {
|
||||
rules = append(rules, &TokenRule{
|
||||
AWSAccount: rule.Account,
|
||||
AWSRegions: rule.Regions,
|
||||
AWSRole: rule.RoleARN,
|
||||
})
|
||||
}
|
||||
}
|
||||
return rules
|
||||
}
|
||||
|
||||
// GetAWSIIDTTL returns the TTL of EC2 IIDs.
|
||||
func (p *ProvisionTokenV3) GetAWSIIDTTL() Duration {
|
||||
ec2 := p.Spec.EC2
|
||||
if ec2 == nil {
|
||||
// `GetAWSIIDTTL()` should never be called for a token that is not ec2
|
||||
// join type - so this branch is unlikely to execute.
|
||||
return 0
|
||||
}
|
||||
return ec2.IIDTTL
|
||||
}
|
||||
|
||||
// GetRoles returns a list of teleport roles
|
||||
// that will be granted to the user of the token
|
||||
// in the credentials.
|
||||
func (p *ProvisionTokenV3) GetRoles() SystemRoles {
|
||||
return p.Spec.Roles
|
||||
}
|
||||
|
||||
// SetRoles sets teleport roles.
|
||||
func (p *ProvisionTokenV3) SetRoles(r SystemRoles) {
|
||||
p.Spec.Roles = r
|
||||
}
|
||||
|
||||
// SetExpiry sets expiry time for the object.
|
||||
func (p *ProvisionTokenV3) SetExpiry(expires time.Time) {
|
||||
p.Metadata.SetExpiry(expires)
|
||||
}
|
||||
|
||||
// Expiry returns object expiry setting.
|
||||
func (p *ProvisionTokenV3) Expiry() time.Time {
|
||||
return p.Metadata.Expiry()
|
||||
}
|
||||
|
||||
// GetName returns token name.
|
||||
func (p *ProvisionTokenV3) GetName() string {
|
||||
return p.Metadata.Name
|
||||
}
|
||||
|
||||
// SetName sets the name of the ProvisionTokenV3.
|
||||
func (p *ProvisionTokenV3) SetName(e string) {
|
||||
p.Metadata.Name = e
|
||||
}
|
||||
|
||||
// GetBotName returns the BotName field which must be set for joining bots.
|
||||
func (p *ProvisionTokenV3) GetBotName() string {
|
||||
return p.Spec.BotName
|
||||
}
|
||||
|
||||
// GetKind returns resource kind.
|
||||
func (p *ProvisionTokenV3) GetKind() string {
|
||||
return p.Kind
|
||||
}
|
||||
|
||||
// GetSubKind returns resource sub kind.
|
||||
func (p *ProvisionTokenV3) GetSubKind() string {
|
||||
return p.SubKind
|
||||
}
|
||||
|
||||
// SetSubKind sets resource subkind.
|
||||
func (p *ProvisionTokenV3) SetSubKind(s string) {
|
||||
p.SubKind = s
|
||||
}
|
||||
|
||||
// GetResourceID returns resource ID.
|
||||
func (p *ProvisionTokenV3) GetResourceID() int64 {
|
||||
return p.Metadata.ID
|
||||
}
|
||||
|
||||
// SetResourceID sets resource ID.
|
||||
func (p *ProvisionTokenV3) SetResourceID(id int64) {
|
||||
p.Metadata.ID = id
|
||||
}
|
||||
|
||||
// GetVersion returns resource version.
|
||||
func (p *ProvisionTokenV3) GetVersion() string {
|
||||
return p.Version
|
||||
}
|
||||
|
||||
// GetMetadata returns metadata.
|
||||
func (p *ProvisionTokenV3) GetMetadata() Metadata {
|
||||
return p.Metadata
|
||||
}
|
||||
|
||||
// SetMetadata sets resource metadata.
|
||||
func (p *ProvisionTokenV3) SetMetadata(meta Metadata) {
|
||||
p.Metadata = meta
|
||||
}
|
||||
|
||||
// GetJoinMethod returns joining method that must be used with this token.
|
||||
func (p *ProvisionTokenV3) GetJoinMethod() JoinMethod {
|
||||
return p.Spec.JoinMethod
|
||||
}
|
||||
|
||||
// GetSuggestedLabels returns the labels the resource should set when using this token
|
||||
func (p *ProvisionTokenV3) GetSuggestedLabels() Labels {
|
||||
return p.Spec.SuggestedLabels
|
||||
}
|
||||
|
||||
// String returns the human readable representation of a provisioning token.
|
||||
func (p ProvisionTokenV3) String() string {
|
||||
expires := "never"
|
||||
if !p.Expiry().IsZero() {
|
||||
expires = p.Expiry().String()
|
||||
}
|
||||
return fmt.Sprintf("ProvisionToken(Roles=%v, Expires=%v)", p.Spec.Roles, expires)
|
||||
}
|
||||
|
||||
// V3 returns the V3 representation of a ProvisionToken
|
||||
func (p *ProvisionTokenV3) V3() *ProvisionTokenV3 {
|
||||
return p
|
||||
}
|
||||
|
||||
var ProvisionTokenNotBackwardsCompatibleErr = trace.Errorf("token cannot be converted to V2 and must be fetched using V3 API")
|
||||
|
||||
// V2 returns the V2 representation of a ProvisionToken
|
||||
// DELETE IN 13.0 (strideynet) - This will no longer be necessary once v2 RPCs
|
||||
// have been removed
|
||||
func (p *ProvisionTokenV3) V2() (*ProvisionTokenV2, error) {
|
||||
v2 := &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V2,
|
||||
Metadata: p.Metadata,
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: p.Spec.Roles,
|
||||
BotName: p.Spec.BotName,
|
||||
JoinMethod: p.Spec.JoinMethod,
|
||||
SuggestedLabels: p.Spec.SuggestedLabels,
|
||||
Allow: p.GetAllowRules(),
|
||||
},
|
||||
}
|
||||
switch p.Spec.JoinMethod {
|
||||
case JoinMethodEC2:
|
||||
v2.Spec.AWSIIDTTL = p.Spec.EC2.IIDTTL
|
||||
case JoinMethodToken, JoinMethodIAM:
|
||||
// No special action to take
|
||||
default:
|
||||
return nil, trace.Wrap(ProvisionTokenNotBackwardsCompatibleErr)
|
||||
}
|
||||
return v2, nil
|
||||
}
|
||||
|
||||
// checkAndSetDefault ensures that the AWS EC2 specific configuration is
|
||||
// valid.
|
||||
// It must provide allow rules, and those allow rules must have account or
|
||||
// role configured.
|
||||
// A default value for IIDTTL is also applied if not provided.
|
||||
func (a *ProvisionTokenSpecV3AWSEC2) checkAndSetDefaults() error {
|
||||
if len(a.Allow) == 0 {
|
||||
return trace.BadParameter("the %q join method requires defined token allow rules", JoinMethodEC2)
|
||||
}
|
||||
for _, allowRule := range a.Allow {
|
||||
if allowRule.Account == "" && allowRule.RoleARN == "" {
|
||||
return trace.BadParameter(
|
||||
`allow rule for %q join method must set "account" or "role"`,
|
||||
JoinMethodEC2,
|
||||
)
|
||||
}
|
||||
}
|
||||
if a.IIDTTL == 0 {
|
||||
// default to 5 minute ttl if unspecified
|
||||
a.IIDTTL = Duration(5 * time.Minute)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkAndSetDefault ensures that the AWS IAM specific configuration is
|
||||
// valid.
|
||||
// It must provide allow rules, and those allow rules must have account or
|
||||
// arn configured.
|
||||
func (a *ProvisionTokenSpecV3AWSIAM) checkAndSetDefaults() error {
|
||||
if len(a.Allow) == 0 {
|
||||
return trace.BadParameter("the %q join method requires defined token allow rules", JoinMethodIAM)
|
||||
}
|
||||
for _, allowRule := range a.Allow {
|
||||
if allowRule.Account == "" && allowRule.ARN == "" {
|
||||
return trace.BadParameter(
|
||||
`allow rule for %q join method must set "account" or "arn"`,
|
||||
JoinMethodEC2,
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -20,617 +20,253 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gravitational/teleport/api/defaults"
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewProvisionToken(t *testing.T) {
|
||||
name := "foo"
|
||||
roles := SystemRoles{RoleNode}
|
||||
expires := time.Date(2000, 1, 1, 1, 1, 1, 1, time.UTC)
|
||||
tok, err := NewProvisionToken(name, roles, expires)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Metadata: Metadata{
|
||||
Name: name,
|
||||
Expires: &expires,
|
||||
Namespace: defaults.Namespace,
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
JoinMethod: JoinMethodToken,
|
||||
Roles: roles,
|
||||
},
|
||||
}, tok)
|
||||
}
|
||||
|
||||
func TestNewProvisionTokenFromSpec(t *testing.T) {
|
||||
name := "foo"
|
||||
expires := time.Date(2000, 1, 1, 1, 1, 1, 1, time.UTC)
|
||||
spec := ProvisionTokenSpecV3{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodToken,
|
||||
}
|
||||
tok, err := NewProvisionTokenFromSpec(name, expires, spec)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Metadata: Metadata{
|
||||
Name: name,
|
||||
Expires: &expires,
|
||||
Namespace: defaults.Namespace,
|
||||
},
|
||||
Spec: spec,
|
||||
}, tok)
|
||||
}
|
||||
|
||||
func TestProvisionTokenV1_V3(t *testing.T) {
|
||||
roles := SystemRoles{RoleNop}
|
||||
name := "foo-tok"
|
||||
expires := time.Date(2000, 1, 1, 1, 1, 1, 1, time.UTC)
|
||||
v1 := ProvisionTokenV1{
|
||||
Roles: roles,
|
||||
Token: name,
|
||||
Expires: expires,
|
||||
}
|
||||
|
||||
v3 := v1.V3()
|
||||
require.Equal(t, &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Metadata: Metadata{
|
||||
Name: name,
|
||||
Expires: &expires,
|
||||
Namespace: defaults.Namespace,
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: roles,
|
||||
JoinMethod: JoinMethodToken,
|
||||
},
|
||||
}, v3)
|
||||
}
|
||||
|
||||
func TestProvisionTokenV2_V3(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
token *ProvisionTokenV2
|
||||
want *ProvisionTokenV3
|
||||
func TestProvisionTokenV2_CheckAndSetDefaults(t *testing.T) {
|
||||
testcases := []struct {
|
||||
desc string
|
||||
token *ProvisionTokenV2
|
||||
expected *ProvisionTokenV2
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
name: "token",
|
||||
desc: "empty",
|
||||
token: &ProvisionTokenV2{},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
desc: "missing roles",
|
||||
token: &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V2,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: SystemRoles{RoleBot},
|
||||
JoinMethod: JoinMethodToken,
|
||||
BotName: "bot-foo",
|
||||
SuggestedLabels: Labels{
|
||||
"label": []string{"foo"},
|
||||
},
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
want: &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
desc: "invalid role",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: SystemRoles{RoleBot},
|
||||
JoinMethod: JoinMethodToken,
|
||||
BotName: "bot-foo",
|
||||
SuggestedLabels: Labels{
|
||||
"label": []string{"foo"},
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode, "not a role"},
|
||||
},
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
desc: "simple token",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
},
|
||||
},
|
||||
expected: &ProvisionTokenV2{
|
||||
Kind: "token",
|
||||
Version: "v2",
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "token",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "iam",
|
||||
desc: "implicit ec2 method",
|
||||
token: &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V2,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodIAM,
|
||||
Roles: []SystemRole{RoleNode},
|
||||
Allow: []*TokenRule{
|
||||
{
|
||||
AWSAccount: "xyzzy",
|
||||
AWSARN: "arn-123",
|
||||
AWSAccount: "1234",
|
||||
AWSRole: "1234/role",
|
||||
AWSRegions: []string{"us-west-2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
expected: &ProvisionTokenV2{
|
||||
Kind: "token",
|
||||
Version: "v2",
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodIAM,
|
||||
IAM: &ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "xyzzy",
|
||||
ARN: "arn-123",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ec2",
|
||||
token: &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V2,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
Name: "test",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodEC2,
|
||||
AWSIIDTTL: NewDuration(time.Second * 37),
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "ec2",
|
||||
Allow: []*TokenRule{
|
||||
{
|
||||
AWSAccount: "a-account",
|
||||
AWSRegions: []string{"a-region"},
|
||||
AWSRole: "a-role",
|
||||
AWSAccount: "1234",
|
||||
AWSRole: "1234/role",
|
||||
AWSRegions: []string{"us-west-2"},
|
||||
},
|
||||
},
|
||||
AWSIIDTTL: Duration(5 * time.Minute),
|
||||
},
|
||||
},
|
||||
want: &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
},
|
||||
{
|
||||
desc: "explicit ec2 method",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodEC2,
|
||||
EC2: &ProvisionTokenSpecV3AWSEC2{
|
||||
IIDTTL: NewDuration(time.Second * 37),
|
||||
Allow: []*ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: "a-account",
|
||||
Regions: []string{"a-region"},
|
||||
RoleARN: "a-role",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "ec2",
|
||||
Allow: []*TokenRule{{AWSAccount: "1234"}},
|
||||
},
|
||||
},
|
||||
expected: &ProvisionTokenV2{
|
||||
Kind: "token",
|
||||
Version: "v2",
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "ec2",
|
||||
Allow: []*TokenRule{{AWSAccount: "1234"}},
|
||||
AWSIIDTTL: Duration(5 * time.Minute),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "ec2 method no allow rules",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "ec2",
|
||||
},
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
desc: "ec2 method with aws_arn",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "ec2",
|
||||
Allow: []*TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "1234",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
v3 := tt.token.V3()
|
||||
require.Equal(t, tt.want, v3)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func validProvisionTokenV3(modifier func(p *ProvisionTokenV3)) *ProvisionTokenV3 {
|
||||
token := &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
Namespace: defaults.Namespace,
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodToken,
|
||||
},
|
||||
}
|
||||
if modifier != nil {
|
||||
modifier(token)
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
func TestProvisionTokenV3_CheckAndSetDefaults(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
token *ProvisionTokenV3
|
||||
// want indicates the token that should be present after the validation
|
||||
// has been called. If this is not provided, the original value of token
|
||||
// is used.
|
||||
want *ProvisionTokenV3
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "valid token",
|
||||
token: validProvisionTokenV3(nil),
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
name: "invalid missing roles",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.Roles = SystemRoles{}
|
||||
}),
|
||||
wantErr: &trace.BadParameterError{},
|
||||
desc: "ec2 method empty rule",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "ec2",
|
||||
Allow: []*TokenRule{{}},
|
||||
},
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
name: "invalid non-existent role",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.Roles = SystemRoles{"supreme_leader"}
|
||||
}),
|
||||
wantErr: &trace.BadParameterError{},
|
||||
desc: "iam method",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "ec2",
|
||||
Allow: []*TokenRule{{AWSAccount: "1234"}},
|
||||
},
|
||||
},
|
||||
expected: &ProvisionTokenV2{
|
||||
Kind: "token",
|
||||
Version: "v2",
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "ec2",
|
||||
Allow: []*TokenRule{{AWSAccount: "1234"}},
|
||||
AWSIIDTTL: Duration(5 * time.Minute),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid bot",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.Roles = SystemRoles{RoleBot}
|
||||
p.Spec.BotName = "a_bot"
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "invalid missing bot name",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.Roles = SystemRoles{RoleBot}
|
||||
}),
|
||||
wantErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
name: "invalid bot name set but not bot token",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.BotName = "set_by_mistake"
|
||||
}),
|
||||
wantErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
name: "missing join method",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.JoinMethod = ""
|
||||
}),
|
||||
wantErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
name: "invalid join method",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.JoinMethod = "ethereal-presence"
|
||||
}),
|
||||
wantErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
name: "missing iam configuration",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.JoinMethod = JoinMethodIAM
|
||||
}),
|
||||
wantErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
name: "missing ec2 configuration",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.JoinMethod = JoinMethodEC2
|
||||
}),
|
||||
wantErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
name: "valid iam configuration",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.JoinMethod = JoinMethodIAM
|
||||
p.Spec.IAM = &ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
desc: "iam method with aws_role",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "iam",
|
||||
Allow: []*TokenRule{
|
||||
{
|
||||
Account: "foo",
|
||||
AWSAccount: "1234",
|
||||
AWSRole: "1234/role",
|
||||
},
|
||||
},
|
||||
}
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
name: "valid ec2 configuration",
|
||||
token: validProvisionTokenV3(func(p *ProvisionTokenV3) {
|
||||
p.Spec.JoinMethod = JoinMethodEC2
|
||||
p.Spec.EC2 = &ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
desc: "iam method with aws_regions",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: "iam",
|
||||
Allow: []*TokenRule{
|
||||
{
|
||||
Account: "foo",
|
||||
AWSAccount: "1234",
|
||||
AWSRegions: []string{"us-west-2"},
|
||||
},
|
||||
},
|
||||
IIDTTL: NewDuration(time.Minute * 12),
|
||||
}
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Ensure we run check n set on a clone - so we can check
|
||||
// for no changes
|
||||
token := proto.Clone(tt.token).(*ProvisionTokenV3)
|
||||
err := token.CheckAndSetDefaults()
|
||||
if tt.wantErr != nil {
|
||||
require.ErrorAs(t, err, &tt.wantErr)
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
err := tc.token.CheckAndSetDefaults()
|
||||
if tc.expectedErr != nil {
|
||||
require.ErrorAs(t, err, &tc.expectedErr)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
want := tt.want
|
||||
if want == nil {
|
||||
want = tt.token
|
||||
}
|
||||
require.Equal(t, want, token)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisionTokenV3_GetAllowRules(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
token ProvisionTokenV3
|
||||
want []*TokenRule
|
||||
}{
|
||||
{
|
||||
name: "ec2",
|
||||
token: ProvisionTokenV3{
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
JoinMethod: JoinMethodEC2,
|
||||
EC2: &ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: "foo",
|
||||
Regions: []string{"eu-west-666", "us-coast-612"},
|
||||
RoleARN: "a-role",
|
||||
},
|
||||
{
|
||||
Account: "bar",
|
||||
Regions: []string{"a-region"},
|
||||
RoleARN: "b-role",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []*TokenRule{
|
||||
{
|
||||
AWSAccount: "foo",
|
||||
AWSRegions: []string{"eu-west-666", "us-coast-612"},
|
||||
AWSRole: "a-role",
|
||||
},
|
||||
{
|
||||
AWSAccount: "bar",
|
||||
AWSRegions: []string{"a-region"},
|
||||
AWSRole: "b-role",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "iam",
|
||||
token: ProvisionTokenV3{
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
JoinMethod: JoinMethodIAM,
|
||||
IAM: &ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "foo",
|
||||
ARN: "arn-amazon-foo",
|
||||
},
|
||||
{
|
||||
Account: "bar",
|
||||
ARN: "arn-amazon-bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []*TokenRule{
|
||||
{
|
||||
AWSAccount: "foo",
|
||||
AWSARN: "arn-amazon-foo",
|
||||
},
|
||||
{
|
||||
AWSAccount: "bar",
|
||||
AWSARN: "arn-amazon-bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
rules := tt.token.GetAllowRules()
|
||||
require.Equal(t, tt.want, rules)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisionTokenV3_GetAWSIIDTTL(t *testing.T) {
|
||||
t.Run("unset", func(t *testing.T) {
|
||||
p := ProvisionTokenV3{
|
||||
Spec: ProvisionTokenSpecV3{},
|
||||
}
|
||||
require.Equal(t, Duration(0), p.GetAWSIIDTTL())
|
||||
})
|
||||
|
||||
t.Run("set", func(t *testing.T) {
|
||||
duration := NewDuration(time.Second * 6)
|
||||
p := ProvisionTokenV3{
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
EC2: &ProvisionTokenSpecV3AWSEC2{
|
||||
IIDTTL: duration,
|
||||
},
|
||||
},
|
||||
}
|
||||
got := p.GetAWSIIDTTL()
|
||||
require.Equal(t, duration, got)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProvisionTokenV3_V2(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
token *ProvisionTokenV3
|
||||
want *ProvisionTokenV2
|
||||
wantError string
|
||||
}{
|
||||
{
|
||||
name: "token",
|
||||
token: &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
BotName: "foo",
|
||||
JoinMethod: JoinMethodToken,
|
||||
SuggestedLabels: Labels{
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V2,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
BotName: "foo",
|
||||
JoinMethod: JoinMethodToken,
|
||||
SuggestedLabels: Labels{
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
Allow: []*TokenRule{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ec2",
|
||||
token: &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodEC2,
|
||||
EC2: &ProvisionTokenSpecV3AWSEC2{
|
||||
IIDTTL: NewDuration(time.Minute * 300),
|
||||
Allow: []*ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: "xyzzy",
|
||||
Regions: []string{"eurasia-1"},
|
||||
RoleARN: "lord-commander",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V2,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodEC2,
|
||||
Allow: []*TokenRule{
|
||||
{
|
||||
AWSAccount: "xyzzy",
|
||||
AWSRegions: []string{"eurasia-1"},
|
||||
AWSRole: "lord-commander",
|
||||
},
|
||||
},
|
||||
AWSIIDTTL: NewDuration(time.Minute * 300),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "iam",
|
||||
token: &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodIAM,
|
||||
IAM: &ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "xyzzy",
|
||||
ARN: "arn-123",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V2,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: JoinMethodIAM,
|
||||
Allow: []*TokenRule{
|
||||
{
|
||||
AWSAccount: "xyzzy",
|
||||
AWSARN: "arn-123",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "inconvertible type",
|
||||
token: &ProvisionTokenV3{
|
||||
Kind: KindToken,
|
||||
Version: V3,
|
||||
Metadata: Metadata{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV3{
|
||||
Roles: SystemRoles{RoleNop},
|
||||
JoinMethod: "join-method-does-not-exist",
|
||||
IAM: &ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "xyzzy",
|
||||
ARN: "arn-123",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
wantError: ProvisionTokenNotBackwardsCompatibleErr.Error(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := tt.token.V2()
|
||||
require.Equal(t, tt.want, got)
|
||||
if tt.wantError != "" {
|
||||
require.EqualError(t, err, tt.wantError)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Equal(t, tc.token, tc.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ import (
|
|||
type StaticTokens interface {
|
||||
// Resource provides common resource properties.
|
||||
Resource
|
||||
// SetStaticTokens sets the list of static tokens used to provision nodes.
|
||||
SetStaticTokens([]ProvisionToken)
|
||||
// GetStaticTokens gets the list of static tokens used to provision nodes.
|
||||
GetStaticTokens() []ProvisionToken
|
||||
}
|
||||
|
@ -104,6 +106,11 @@ func (c *StaticTokensV2) GetMetadata() Metadata {
|
|||
return c.Metadata
|
||||
}
|
||||
|
||||
// SetStaticTokens sets the list of static tokens used to provision nodes.
|
||||
func (c *StaticTokensV2) SetStaticTokens(s []ProvisionToken) {
|
||||
c.Spec.StaticTokens = ProvisionTokensToV1(s)
|
||||
}
|
||||
|
||||
// GetStaticTokens gets the list of static tokens used to provision nodes.
|
||||
func (c *StaticTokensV2) GetStaticTokens() []ProvisionToken {
|
||||
return ProvisionTokensFromV1(c.Spec.StaticTokens)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -158,15 +158,12 @@ func TestEC2NodeJoin(t *testing.T) {
|
|||
token, err := types.NewProvisionTokenFromSpec(
|
||||
tokenName,
|
||||
time.Now().Add(time.Hour),
|
||||
types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: iid.AccountID,
|
||||
Regions: []string{iid.Region},
|
||||
},
|
||||
types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: iid.AccountID,
|
||||
AWSRegions: []string{iid.Region},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
@ -236,16 +233,14 @@ func TestIAMNodeJoin(t *testing.T) {
|
|||
token, err := types.NewProvisionTokenFromSpec(
|
||||
tokenName,
|
||||
time.Now().Add(time.Hour),
|
||||
types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode, types.RoleProxy},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: *id.Account,
|
||||
},
|
||||
types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode, types.RoleProxy},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: *id.Account,
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
Copyright 2022 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
)
|
||||
|
||||
func MustCreateProvisionToken(token string, roles types.SystemRoles, expires time.Time) types.ProvisionToken {
|
||||
t, err := types.NewProvisionToken(token, roles, expires)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
|
@ -2162,7 +2162,7 @@ func testMapRoles(t *testing.T, suite *integrationTestSuite) {
|
|||
require.NoError(t, err)
|
||||
trustedClusterToken := "trusted-cluster-token"
|
||||
err = main.Process.GetAuthServer().UpsertToken(ctx,
|
||||
helpers.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
services.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
require.NoError(t, err)
|
||||
trustedCluster := main.AsTrustedCluster(trustedClusterToken, types.RoleMap{
|
||||
{Remote: mainDevs, Local: []string{auxDevs}},
|
||||
|
@ -2667,7 +2667,7 @@ func testTrustedTunnelNode(t *testing.T, suite *integrationTestSuite) {
|
|||
require.NoError(t, err)
|
||||
trustedClusterToken := "trusted-cluster-token"
|
||||
err = main.Process.GetAuthServer().UpsertToken(ctx,
|
||||
helpers.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
services.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
require.NoError(t, err)
|
||||
trustedCluster := main.AsTrustedCluster(trustedClusterToken, types.RoleMap{
|
||||
{Remote: mainDevs, Local: []string{auxDevs}},
|
||||
|
@ -4263,7 +4263,7 @@ func testRotateTrustedClusters(t *testing.T, suite *integrationTestSuite) {
|
|||
require.NoError(t, err)
|
||||
trustedClusterToken := "trusted-cluster-token"
|
||||
err = svc.GetAuthServer().UpsertToken(ctx,
|
||||
helpers.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
services.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
require.NoError(t, err)
|
||||
trustedCluster := main.AsTrustedCluster(trustedClusterToken, types.RoleMap{
|
||||
{Remote: mainDevs, Local: []string{auxDevs}},
|
||||
|
|
|
@ -43,6 +43,7 @@ import (
|
|||
"github.com/gravitational/teleport/lib/client"
|
||||
"github.com/gravitational/teleport/lib/events"
|
||||
"github.com/gravitational/teleport/lib/service"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/session"
|
||||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
@ -540,7 +541,7 @@ func testKubeTrustedClustersClientCert(t *testing.T, suite *KubeSuite) {
|
|||
require.NoError(t, err)
|
||||
trustedClusterToken := "trusted-clsuter-token"
|
||||
err = main.Process.GetAuthServer().UpsertToken(ctx,
|
||||
helpers.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
services.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
require.NoError(t, err)
|
||||
trustedCluster := main.AsTrustedCluster(trustedClusterToken, types.RoleMap{
|
||||
{Remote: mainRole.GetName(), Local: []string{auxRole.GetName()}},
|
||||
|
@ -795,7 +796,7 @@ func testKubeTrustedClustersSNI(t *testing.T, suite *KubeSuite) {
|
|||
require.NoError(t, err)
|
||||
trustedClusterToken := "trusted-cluster-token"
|
||||
err = main.Process.GetAuthServer().UpsertToken(ctx,
|
||||
helpers.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
services.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
require.NoError(t, err)
|
||||
trustedCluster := main.AsTrustedCluster(trustedClusterToken, types.RoleMap{
|
||||
{Remote: mainRole.GetName(), Local: []string{auxRole.GetName()}},
|
||||
|
|
|
@ -382,7 +382,7 @@ func withTrustedCluster() proxySuiteOptionsFunc {
|
|||
|
||||
trustedClusterToken := "trustedclustertoken"
|
||||
err := root.Process.GetAuthServer().UpsertToken(context.Background(),
|
||||
helpers.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
types.MustCreateProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}))
|
||||
require.NoError(t, err)
|
||||
trustedCluster := root.AsTrustedCluster(trustedClusterToken, types.RoleMap{
|
||||
{Remote: rootRole.GetName(), Local: []string{secondRole.GetName()}},
|
||||
|
|
|
@ -289,7 +289,7 @@ func (s *Server) checkOrCreateBotToken(ctx context.Context, req *proto.CreateBot
|
|||
ttl = defaults.DefaultBotJoinTTL
|
||||
}
|
||||
|
||||
tokenSpec := types.ProvisionTokenSpecV3{
|
||||
tokenSpec := types.ProvisionTokenSpecV2{
|
||||
Roles: types.SystemRoles{types.RoleBot},
|
||||
JoinMethod: types.JoinMethodToken,
|
||||
BotName: botName,
|
||||
|
|
|
@ -2922,8 +2922,7 @@ func (g *GRPCServer) DeleteTrustedCluster(ctx context.Context, req *types.Resour
|
|||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// GetToken retrieves a v2 token by name.
|
||||
// DELETE IN 13
|
||||
// GetToken retrieves a token by name.
|
||||
func (g *GRPCServer) GetToken(ctx context.Context, req *types.ResourceRequest) (*types.ProvisionTokenV2, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
|
@ -2933,32 +2932,14 @@ func (g *GRPCServer) GetToken(ctx context.Context, req *types.ResourceRequest) (
|
|||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
v2, err := t.V2()
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
provisionTokenV2, ok := t.(*types.ProvisionTokenV2)
|
||||
if !ok {
|
||||
return nil, trace.Errorf("encountered unexpected token type: %T", t)
|
||||
}
|
||||
|
||||
return v2, nil
|
||||
}
|
||||
|
||||
// GetTokenV3 retrieves a token by name.
|
||||
// If the specified token is v2, it will be converted to v3.
|
||||
func (g *GRPCServer) GetTokenV3(ctx context.Context, req *types.ResourceRequest) (*types.ProvisionTokenV3, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
t, err := auth.ServerWithRoles.GetToken(ctx, req.Name)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return t.V3(), nil
|
||||
return provisionTokenV2, nil
|
||||
}
|
||||
|
||||
// GetTokens retrieves all tokens.
|
||||
// DELETE IN 13
|
||||
func (g *GRPCServer) GetTokens(ctx context.Context, _ *emptypb.Empty) (*types.ProvisionTokenV2List, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
|
@ -2968,54 +2949,20 @@ func (g *GRPCServer) GetTokens(ctx context.Context, _ *emptypb.Empty) (*types.Pr
|
|||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
provisionTokensV2 := make([]*types.ProvisionTokenV2, 0, len(ts))
|
||||
for _, t := range ts {
|
||||
v2, err := t.V2()
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
provisionTokensV2 := make([]*types.ProvisionTokenV2, len(ts))
|
||||
for i, t := range ts {
|
||||
var ok bool
|
||||
if provisionTokensV2[i], ok = t.(*types.ProvisionTokenV2); !ok {
|
||||
return nil, trace.Errorf("encountered unexpected token type: %T", t)
|
||||
}
|
||||
provisionTokensV2 = append(provisionTokensV2, v2)
|
||||
}
|
||||
return &types.ProvisionTokenV2List{
|
||||
ProvisionTokens: provisionTokensV2,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetTokensV3 retrieves all tokens.
|
||||
// V2 tokens will be converted to V3 for presentation.
|
||||
func (g *GRPCServer) GetTokensV3(ctx context.Context, _ *emptypb.Empty) (*types.ProvisionTokenV3List, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
ts, err := auth.ServerWithRoles.GetTokens(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
v3Tokens := make([]*types.ProvisionTokenV3, len(ts))
|
||||
for i, t := range ts {
|
||||
v3Tokens[i] = t.V3()
|
||||
}
|
||||
return &types.ProvisionTokenV3List{
|
||||
ProvisionTokens: v3Tokens,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpsertToken upserts a token.
|
||||
// DELETE IN 13
|
||||
func (g *GRPCServer) UpsertToken(ctx context.Context, token *types.ProvisionTokenV2) (*emptypb.Empty, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
if err = auth.ServerWithRoles.UpsertToken(ctx, token.V3()); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// UpsertTokenV3 upserts a v3 token.
|
||||
func (g *GRPCServer) UpsertTokenV3(ctx context.Context, token *types.ProvisionTokenV3) (*emptypb.Empty, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
@ -3027,20 +2974,7 @@ func (g *GRPCServer) UpsertTokenV3(ctx context.Context, token *types.ProvisionTo
|
|||
}
|
||||
|
||||
// CreateToken creates a token.
|
||||
// DELETE IN 13
|
||||
func (g *GRPCServer) CreateToken(ctx context.Context, token *types.ProvisionTokenV2) (*emptypb.Empty, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
if err = auth.ServerWithRoles.CreateToken(ctx, token.V3()); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// CreateTokenV3 creates a v3 token.
|
||||
func (g *GRPCServer) CreateTokenV3(ctx context.Context, token *types.ProvisionTokenV3) (*emptypb.Empty, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
|
|
@ -169,7 +169,7 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
tokenSpec types.ProvisionTokenSpecV3
|
||||
tokenSpec types.ProvisionTokenSpecV2
|
||||
ec2Client ec2Client
|
||||
request types.RegisterUsingTokenRequest
|
||||
expectError func(error) bool
|
||||
|
@ -177,15 +177,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
desc: "basic passing case",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -202,19 +199,16 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "pass with multiple rules",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance2.account,
|
||||
Regions: []string{instance2.region},
|
||||
},
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance2.account,
|
||||
AWSRegions: []string{instance2.region},
|
||||
},
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -231,15 +225,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "pass with multiple regions",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{"us-east-1", instance1.region, "us-east-2"},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{"us-east-1", instance1.region, "us-east-2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -256,14 +247,11 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "pass with no regions",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -280,15 +268,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "wrong account",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: "bad account",
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "bad account",
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -305,15 +290,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "wrong region",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{"bad region"},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{"bad region"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -330,15 +312,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "bad HostID",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -355,15 +334,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "no identity document",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -379,15 +355,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "bad identity document",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -404,15 +377,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "instance already joined",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance2.account,
|
||||
Regions: []string{instance2.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance2.account,
|
||||
AWSRegions: []string{instance2.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -429,15 +399,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "instance already joined, fake ID",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance2.account,
|
||||
Regions: []string{instance2.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance2.account,
|
||||
AWSRegions: []string{instance2.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -454,15 +421,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "instance not running",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -479,15 +443,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "instance not exists",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -504,15 +465,12 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "TTL expired",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -529,18 +487,15 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "custom TTL pass",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
IIDTTL: types.Duration(10 * time.Minute),
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
AWSIIDTTL: types.Duration(10 * time.Minute),
|
||||
},
|
||||
ec2Client: ec2ClientRunning{},
|
||||
request: types.RegisterUsingTokenRequest{
|
||||
|
@ -555,18 +510,15 @@ func TestAuth_RegisterUsingToken_EC2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "custom TTL fail",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
IIDTTL: types.Duration(10 * time.Minute),
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
AWSIIDTTL: types.Duration(10 * time.Minute),
|
||||
},
|
||||
ec2Client: ec2ClientRunning{},
|
||||
request: types.RegisterUsingTokenRequest{
|
||||
|
@ -634,8 +586,7 @@ func TestHostUniqueCheck(t *testing.T) {
|
|||
token, err := types.NewProvisionTokenFromSpec(
|
||||
"test_token",
|
||||
time.Now().Add(time.Minute),
|
||||
types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodEC2,
|
||||
types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{
|
||||
types.RoleNode,
|
||||
types.RoleProxy,
|
||||
|
@ -644,12 +595,10 @@ func TestHostUniqueCheck(t *testing.T) {
|
|||
types.RoleApp,
|
||||
types.RoleWindowsDesktop,
|
||||
},
|
||||
EC2: &types.ProvisionTokenSpecV3AWSEC2{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSEC2_Rule{
|
||||
{
|
||||
Account: instance1.account,
|
||||
Regions: []string{instance1.region},
|
||||
},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: instance1.account,
|
||||
AWSRegions: []string{instance1.region},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
@ -132,7 +132,7 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc string
|
||||
tokenName string
|
||||
requestTokenName string
|
||||
tokenSpec types.ProvisionTokenSpecV3
|
||||
tokenSpec types.ProvisionTokenSpecV2
|
||||
stsClient stsClient
|
||||
iamRegisterOptions []iamRegisterOption
|
||||
challengeResponseOptions []challengeResponseOption
|
||||
|
@ -143,17 +143,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "basic passing case",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -168,17 +166,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "wildcard arn 1",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::role/admins-*",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::role/admins-*",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -193,17 +189,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "wildcard arn 2",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::role/admins-???",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::role/admins-???",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -218,17 +212,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "wrong token",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "wrong-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -243,17 +235,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "challenge response error",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -269,17 +259,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "wrong arn",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::role/admins-???",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::role/admins-???",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -294,17 +282,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "wrong challenge",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -322,17 +308,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "wrong account",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -347,17 +331,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "sts api error",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusForbidden,
|
||||
|
@ -369,17 +351,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "wrong sts host",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -397,17 +377,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "regional sts endpoint",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -425,17 +403,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "unsigned challenge header",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -453,17 +429,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "fips pass",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -485,17 +459,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "non-fips client pass v11",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -517,17 +489,15 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
desc: "non-fips client fail v12",
|
||||
tokenName: "test-token",
|
||||
requestTokenName: "test-token",
|
||||
tokenSpec: types.ProvisionTokenSpecV3{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
IAM: &types.ProvisionTokenSpecV3AWSIAM{
|
||||
Allow: []*types.ProvisionTokenSpecV3AWSIAM_Rule{
|
||||
{
|
||||
Account: "1234",
|
||||
ARN: "arn:aws::1111",
|
||||
},
|
||||
tokenSpec: types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{types.RoleNode},
|
||||
Allow: []*types.TokenRule{
|
||||
{
|
||||
AWSAccount: "1234",
|
||||
AWSARN: "arn:aws::1111",
|
||||
},
|
||||
},
|
||||
JoinMethod: types.JoinMethodIAM,
|
||||
},
|
||||
stsClient: &mockClient{
|
||||
respStatusCode: http.StatusOK,
|
||||
|
@ -555,7 +525,6 @@ func TestAuth_RegisterUsingIAMMethod(t *testing.T) {
|
|||
time.Now().Add(time.Minute),
|
||||
tc.tokenSpec)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, a.UpsertToken(ctx, token))
|
||||
defer func() {
|
||||
require.NoError(t, a.DeleteToken(ctx, token.GetName()))
|
||||
|
|
|
@ -258,10 +258,9 @@ func TestAuth_RegisterUsingToken(t *testing.T) {
|
|||
|
||||
func newBotToken(t *testing.T, tokenName, botName string, role types.SystemRole, expiry time.Time) types.ProvisionToken {
|
||||
t.Helper()
|
||||
token, err := types.NewProvisionTokenFromSpec(tokenName, expiry, types.ProvisionTokenSpecV3{
|
||||
JoinMethod: types.JoinMethodToken,
|
||||
Roles: []types.SystemRole{role},
|
||||
BotName: botName,
|
||||
token, err := types.NewProvisionTokenFromSpec(tokenName, expiry, types.ProvisionTokenSpecV2{
|
||||
Roles: []types.SystemRole{role},
|
||||
BotName: botName,
|
||||
})
|
||||
require.NoError(t, err, "could not create bot token")
|
||||
return token
|
||||
|
|
|
@ -3350,7 +3350,7 @@ func TestEventsClusterConfig(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
suite.ExpectDeleteResource(t, w, 3*time.Second, &types.ResourceHeader{
|
||||
Kind: types.KindToken,
|
||||
Version: types.VDeleted,
|
||||
Version: types.V2,
|
||||
Metadata: types.Metadata{
|
||||
Namespace: apidefaults.Namespace,
|
||||
Name: token.GetName(),
|
||||
|
|
2
lib/cache/cache_test.go
vendored
2
lib/cache/cache_test.go
vendored
|
@ -2674,7 +2674,7 @@ func TestCacheWatchKindExistsInEvents(t *testing.T) {
|
|||
types.KindClusterAuthPreference: types.DefaultAuthPreference(),
|
||||
types.KindSessionRecordingConfig: types.DefaultSessionRecordingConfig(),
|
||||
types.KindStaticTokens: &types.StaticTokensV2{},
|
||||
types.KindToken: &types.ProvisionTokenV3{},
|
||||
types.KindToken: &types.ProvisionTokenV2{},
|
||||
types.KindUser: &types.UserV2{},
|
||||
types.KindRole: &types.RoleV5{Version: types.V4},
|
||||
types.KindNamespace: &types.Namespace{},
|
||||
|
|
|
@ -336,7 +336,7 @@ type provisionTokenParser struct {
|
|||
func (p *provisionTokenParser) parse(event backend.Event) (types.Resource, error) {
|
||||
switch event.Type {
|
||||
case types.OpDelete:
|
||||
return resourceHeader(event, types.KindToken, types.VDeleted, 0)
|
||||
return resourceHeader(event, types.KindToken, types.V2, 0)
|
||||
case types.OpPut:
|
||||
token, err := services.UnmarshalProvisionToken(event.Item.Value,
|
||||
services.WithResourceID(event.Item.ID),
|
||||
|
|
|
@ -18,6 +18,7 @@ package services
|
|||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
|
||||
|
@ -47,6 +48,16 @@ type Provisioner interface {
|
|||
GetTokens(ctx context.Context) ([]types.ProvisionToken, error)
|
||||
}
|
||||
|
||||
// MustCreateProvisionToken returns a new valid provision token
|
||||
// or panics, used in tests
|
||||
func MustCreateProvisionToken(token string, roles types.SystemRoles, expires time.Time) types.ProvisionToken {
|
||||
t, err := types.NewProvisionToken(token, roles, expires)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// UnmarshalProvisionToken unmarshals the ProvisionToken resource from JSON.
|
||||
func UnmarshalProvisionToken(data []byte, opts ...MarshalOption) (types.ProvisionToken, error) {
|
||||
if len(data) == 0 {
|
||||
|
@ -66,38 +77,21 @@ func UnmarshalProvisionToken(data []byte, opts ...MarshalOption) (types.Provisio
|
|||
|
||||
switch h.Version {
|
||||
case "":
|
||||
// ProvisionTokenV1 is converted to V3, as ProvisionTokenV1 no longer
|
||||
// implements the ProvisionToken interface.
|
||||
var p types.ProvisionTokenV1
|
||||
err := utils.FastUnmarshal(data, &p)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
v3 := p.V3()
|
||||
v2 := p.V2()
|
||||
if cfg.ID != 0 {
|
||||
v3.SetResourceID(cfg.ID)
|
||||
v2.SetResourceID(cfg.ID)
|
||||
}
|
||||
return v3, nil
|
||||
return v2, nil
|
||||
case types.V2:
|
||||
// ProvisionTokenV2 is converted to V3, as ProvisionTokenV2 is no
|
||||
// longer supported.
|
||||
var p types.ProvisionTokenV2
|
||||
if err := utils.FastUnmarshal(data, &p); err != nil {
|
||||
return nil, trace.BadParameter(err.Error())
|
||||
}
|
||||
v3 := p.V3()
|
||||
if cfg.ID != 0 {
|
||||
v3.SetResourceID(cfg.ID)
|
||||
}
|
||||
if err := v3.CheckAndSetDefaults(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return v3, nil
|
||||
case types.V3:
|
||||
var p types.ProvisionTokenV3
|
||||
if err := utils.FastUnmarshal(data, &p); err != nil {
|
||||
return nil, trace.BadParameter(err.Error())
|
||||
}
|
||||
if err := p.CheckAndSetDefaults(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
@ -121,7 +115,7 @@ func MarshalProvisionToken(provisionToken types.ProvisionToken, opts ...MarshalO
|
|||
}
|
||||
|
||||
switch provisionToken := provisionToken.(type) {
|
||||
case *types.ProvisionTokenV3:
|
||||
case *types.ProvisionTokenV2:
|
||||
if !cfg.PreserveResourceID {
|
||||
// avoid modifying the original object
|
||||
// to prevent unexpected data races
|
||||
|
@ -129,6 +123,9 @@ func MarshalProvisionToken(provisionToken types.ProvisionToken, opts ...MarshalO
|
|||
copy.SetResourceID(0)
|
||||
provisionToken = ©
|
||||
}
|
||||
if cfg.GetVersion() == types.V1 {
|
||||
return utils.FastMarshal(provisionToken.V1())
|
||||
}
|
||||
return utils.FastMarshal(provisionToken)
|
||||
default:
|
||||
return nil, trace.BadParameter("unrecognized provision token version %T", provisionToken)
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
Copyright 2022 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/teleport/api/defaults"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
"github.com/gravitational/teleport/lib/utils/golden"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func mustCreateProvisionToken(token string, roles types.SystemRoles, expires time.Time) types.ProvisionToken {
|
||||
t, err := types.NewProvisionToken(token, roles, expires)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func TestUnmarshalProvisionToken(t *testing.T) {
|
||||
expiry := time.Date(2000, 0, 0, 0, 0, 0, 0, time.UTC)
|
||||
tests := []struct {
|
||||
name string
|
||||
data []byte
|
||||
opts []MarshalOption
|
||||
want types.ProvisionToken
|
||||
}{
|
||||
{
|
||||
name: "v1",
|
||||
data: []byte(`{"roles":["Nop"],"token":"foo","expires":"1999-11-30T00:00:00Z"}`),
|
||||
want: (&types.ProvisionTokenV1{
|
||||
Token: "foo",
|
||||
Roles: types.SystemRoles{types.RoleNop},
|
||||
Expires: expiry,
|
||||
}).V3(),
|
||||
},
|
||||
{
|
||||
name: "v2",
|
||||
data: []byte(`{"kind":"token","version":"v2","metadata":{"name":"foo","expires":"1999-11-30T00:00:00Z"},"spec":{"roles":["Nop"],"join_method":"token"}}`),
|
||||
want: (&types.ProvisionTokenV2{
|
||||
Kind: types.KindToken,
|
||||
Version: types.V2,
|
||||
Metadata: types.Metadata{
|
||||
Name: "foo",
|
||||
Expires: &expiry,
|
||||
Namespace: defaults.Namespace,
|
||||
},
|
||||
Spec: types.ProvisionTokenSpecV2{
|
||||
Roles: types.SystemRoles{types.RoleNop},
|
||||
JoinMethod: types.JoinMethodToken,
|
||||
},
|
||||
}).V3(),
|
||||
},
|
||||
{
|
||||
name: "v3",
|
||||
data: []byte(`{"kind":"token","version":"v3","metadata":{"name":"foo","expires":"1999-11-30T00:00:00Z"},"spec":{"roles":["Nop"],"join_method":"token"}}`),
|
||||
want: mustCreateProvisionToken(
|
||||
"foo",
|
||||
types.SystemRoles{types.RoleNop},
|
||||
expiry,
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := UnmarshalProvisionToken(tt.data, tt.opts...)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalProvisionToken(t *testing.T) {
|
||||
v3 := mustCreateProvisionToken(
|
||||
"foo",
|
||||
types.SystemRoles{types.RoleNop},
|
||||
time.Date(2000, 0, 0, 0, 0, 0, 0, time.UTC),
|
||||
)
|
||||
v3.SetResourceID(1337)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
token types.ProvisionToken
|
||||
opts []MarshalOption
|
||||
}{
|
||||
{
|
||||
name: "v3",
|
||||
token: v3,
|
||||
},
|
||||
{
|
||||
name: "v3 - PreserveResourceID",
|
||||
token: v3,
|
||||
opts: []MarshalOption{PreserveResourceID()},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
bytes, err := MarshalProvisionToken(tt.token, tt.opts...)
|
||||
require.NoError(t, err)
|
||||
if golden.ShouldSet() {
|
||||
golden.Set(t, bytes)
|
||||
}
|
||||
require.Equal(t, golden.Get(t), bytes)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -647,6 +647,29 @@ func (s *ServicesTestSuite) TokenCRUD(t *testing.T) {
|
|||
_, err = s.ProvisioningS.GetToken(ctx, "token")
|
||||
require.True(t, trace.IsNotFound(err))
|
||||
|
||||
// check tokens backwards compatibility and marshal/unmarshal
|
||||
expiry := time.Now().UTC().Add(time.Hour)
|
||||
v1 := &types.ProvisionTokenV1{
|
||||
Token: "old",
|
||||
Roles: types.SystemRoles{types.RoleNode, types.RoleProxy},
|
||||
Expires: expiry,
|
||||
}
|
||||
v2, err := types.NewProvisionToken(v1.Token, v1.Roles, expiry)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Tokens in different version formats are backwards and forwards
|
||||
// compatible
|
||||
require.Empty(t, cmp.Diff(v1.V2(), v2))
|
||||
require.Empty(t, cmp.Diff(v2.V1(), v1))
|
||||
|
||||
// Marshal V1, unmarshal V2
|
||||
data, err := services.MarshalProvisionToken(v2, services.WithVersion(types.V1))
|
||||
require.NoError(t, err)
|
||||
|
||||
out, err := services.UnmarshalProvisionToken(data)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, cmp.Diff(out, v2))
|
||||
|
||||
// Test delete all tokens
|
||||
tok, err = types.NewProvisionToken("token1", types.SystemRoles{types.RoleAuth, types.RoleNode}, time.Time{})
|
||||
require.NoError(t, err)
|
||||
|
@ -1374,7 +1397,6 @@ func (s *ServicesTestSuite) Events(t *testing.T) {
|
|||
kind: types.WatchKind{
|
||||
Kind: types.KindToken,
|
||||
},
|
||||
expectDeleteVersion: true,
|
||||
crud: func(context.Context) types.Resource {
|
||||
expires := time.Now().UTC().Add(time.Hour)
|
||||
tok, err := types.NewProvisionToken("token",
|
||||
|
@ -1821,18 +1843,14 @@ skiploop:
|
|||
}
|
||||
// delete events don't have IDs yet
|
||||
header.SetResourceID(0)
|
||||
if tc.expectDeleteVersion {
|
||||
header.Version = types.VDeleted
|
||||
}
|
||||
ExpectDeleteResource(t, w, 3*time.Second, header)
|
||||
}
|
||||
}
|
||||
|
||||
type eventTest struct {
|
||||
name string
|
||||
kind types.WatchKind
|
||||
expectDeleteVersion bool
|
||||
crud func(context.Context) types.Resource
|
||||
name string
|
||||
kind types.WatchKind
|
||||
crud func(context.Context) types.Resource
|
||||
}
|
||||
|
||||
func eventsTestKinds(tests []eventTest) []types.WatchKind {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
{"kind":"token","version":"v3","metadata":{"name":"foo","expires":"1999-11-30T00:00:00Z"},"spec":{"roles":["Nop"],"join_method":"token"}}
|
|
@ -1 +0,0 @@
|
|||
{"kind":"token","version":"v3","metadata":{"name":"foo","expires":"1999-11-30T00:00:00Z","id":1337},"spec":{"roles":["Nop"],"join_method":"token"}}
|
|
@ -70,9 +70,6 @@ type scriptSettings struct {
|
|||
}
|
||||
|
||||
func (h *Handler) createTokenHandle(w http.ResponseWriter, r *http.Request, params httprouter.Params, ctx *SessionContext) (interface{}, error) {
|
||||
// TODO: This API needs to switch to ProvisionTokenSpecV3 down the road
|
||||
// Is there a reasonable way for us to determine v2 vs v3 specs - or
|
||||
// do we need to introduce a separate endpoint.
|
||||
var req types.ProvisionTokenSpecV2
|
||||
if err := httplib.ReadJSON(r, &req); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
@ -137,14 +134,10 @@ func (h *Handler) createTokenHandle(w http.ResponseWriter, r *http.Request, para
|
|||
types.InternalResourceIDLabel: apiutils.Strings{uuid.NewString()},
|
||||
}
|
||||
|
||||
v2 := types.ProvisionTokenV2{
|
||||
Metadata: types.Metadata{
|
||||
Name: tokenName,
|
||||
Expires: &expires,
|
||||
},
|
||||
Spec: req,
|
||||
provisionToken, err := types.NewProvisionTokenFromSpec(tokenName, expires, req)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
provisionToken := v2.V3()
|
||||
|
||||
err = clt.CreateToken(r.Context(), provisionToken)
|
||||
if err != nil {
|
||||
|
|
|
@ -303,11 +303,11 @@ func TestGetNodeJoinScript(t *testing.T) {
|
|||
},
|
||||
mockGetToken: func(_ context.Context, token string) (types.ProvisionToken, error) {
|
||||
if token == validToken || token == validIAMToken {
|
||||
return &types.ProvisionTokenV3{
|
||||
return &types.ProvisionTokenV2{
|
||||
Metadata: types.Metadata{
|
||||
Name: token,
|
||||
},
|
||||
Spec: types.ProvisionTokenSpecV3{
|
||||
Spec: types.ProvisionTokenSpecV2{
|
||||
SuggestedLabels: types.Labels{
|
||||
types.InternalResourceIDLabel: utils.Strings{internalResourceID},
|
||||
},
|
||||
|
@ -399,7 +399,7 @@ func TestGetAppJoinScript(t *testing.T) {
|
|||
m := &mockedNodeAPIGetter{
|
||||
mockGetToken: func(_ context.Context, token string) (types.ProvisionToken, error) {
|
||||
if token == testTokenID {
|
||||
return &types.ProvisionTokenV3{
|
||||
return &types.ProvisionTokenV2{
|
||||
Metadata: types.Metadata{
|
||||
Name: token,
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue