mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-02 06:08:23 +08:00
GitLab Delegated Joining (#22705)
* Add type for GitLab ProvisionToken * Add default behaviour for domain * Add IDTokenClaims for GitLab * Add gitlab token source and token validator * Thread GitLab support through auth and tbot packages * Adjust cluster name fetching in token validator * Initialize GitLab token validator in auth * Improve comment on `sub` * Working GitLab CI delegated joining * Add additional token rule fields * Add checking for new configuration fields * add additional test cases for validation of gitlab config struct * Add TestAuth_RegisterUsingToken_GitLab * Add tests for IDTokenSource * Fix imports * Add tests for GitLab Token Validator * Fix some comments that were incomplete * Add license headers
This commit is contained in:
@@ -55,6 +55,10 @@ const (
|
||||
// JoinMethodAzure indicates that the node will join with the Azure join
|
||||
// method.
|
||||
JoinMethodAzure JoinMethod = "azure"
|
||||
// JoinMethodGitLab indicates that the node will join with the GitLab
|
||||
// join method. Documentation regarding implementation of this
|
||||
// can be found in lib/gitlab
|
||||
JoinMethodGitLab JoinMethod = "gitlab"
|
||||
)
|
||||
|
||||
var JoinMethods = []JoinMethod{
|
||||
@@ -65,6 +69,7 @@ var JoinMethods = []JoinMethod{
|
||||
JoinMethodCircleCI,
|
||||
JoinMethodKubernetes,
|
||||
JoinMethodAzure,
|
||||
JoinMethodGitLab,
|
||||
}
|
||||
|
||||
func ValidateJoinMethod(method JoinMethod) error {
|
||||
@@ -267,6 +272,17 @@ func (p *ProvisionTokenV2) CheckAndSetDefaults() error {
|
||||
if err := providerCfg.checkAndSetDefaults(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
case JoinMethodGitLab:
|
||||
providerCfg := p.Spec.GitLab
|
||||
if providerCfg == nil {
|
||||
return trace.BadParameter(
|
||||
`"gitlab" configuration must be provided for the join method %q`,
|
||||
JoinMethodGitLab,
|
||||
)
|
||||
}
|
||||
if err := providerCfg.checkAndSetDefaults(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
default:
|
||||
return trace.BadParameter("unknown join method %q", p.Spec.JoinMethod)
|
||||
}
|
||||
@@ -567,3 +583,33 @@ func (a *ProvisionTokenSpecV2Azure) checkAndSetDefaults() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const defaultGitLabDomain = "gitlab.com"
|
||||
|
||||
func (a *ProvisionTokenSpecV2GitLab) checkAndSetDefaults() error {
|
||||
if len(a.Allow) == 0 {
|
||||
return trace.BadParameter(
|
||||
"the %q join method requires defined gitlab allow rules",
|
||||
JoinMethodGitLab,
|
||||
)
|
||||
}
|
||||
for _, allowRule := range a.Allow {
|
||||
if allowRule.Sub == "" && allowRule.NamespacePath == "" && allowRule.ProjectPath == "" {
|
||||
return trace.BadParameter(
|
||||
"the %q join method requires allow rules with at least 'sub', 'project_path' or 'namespace_path' to ensure security.",
|
||||
JoinMethodGitLab,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if a.Domain == "" {
|
||||
a.Domain = defaultGitLabDomain
|
||||
} else {
|
||||
if strings.Contains(a.Domain, "/") {
|
||||
return trace.BadParameter(
|
||||
"'spec.gitlab.domain' should not contain the scheme or path",
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import (
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/gravitational/teleport/api/defaults"
|
||||
)
|
||||
|
||||
func TestProvisionTokenV2_CheckAndSetDefaults(t *testing.T) {
|
||||
@@ -448,6 +450,154 @@ func TestProvisionTokenV2_CheckAndSetDefaults(t *testing.T) {
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
desc: "gitlab empty allow rules",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: JoinMethodGitLab,
|
||||
GitLab: &ProvisionTokenSpecV2GitLab{
|
||||
Allow: []*ProvisionTokenSpecV2GitLab_Rule{},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
desc: "gitlab missing config",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: JoinMethodGitLab,
|
||||
GitLab: nil,
|
||||
},
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
desc: "gitlab empty allow rule",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: JoinMethodGitLab,
|
||||
GitLab: &ProvisionTokenSpecV2GitLab{
|
||||
Allow: []*ProvisionTokenSpecV2GitLab_Rule{
|
||||
{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
{
|
||||
desc: "gitlab defaults",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: JoinMethodGitLab,
|
||||
GitLab: &ProvisionTokenSpecV2GitLab{
|
||||
Allow: []*ProvisionTokenSpecV2GitLab_Rule{
|
||||
{
|
||||
Sub: "asub",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V2,
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
Namespace: defaults.Namespace,
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: JoinMethodGitLab,
|
||||
GitLab: &ProvisionTokenSpecV2GitLab{
|
||||
Allow: []*ProvisionTokenSpecV2GitLab_Rule{
|
||||
{
|
||||
Sub: "asub",
|
||||
},
|
||||
},
|
||||
Domain: defaultGitLabDomain,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "overridden domain",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: JoinMethodGitLab,
|
||||
GitLab: &ProvisionTokenSpecV2GitLab{
|
||||
Allow: []*ProvisionTokenSpecV2GitLab_Rule{
|
||||
{
|
||||
Sub: "asub",
|
||||
},
|
||||
},
|
||||
Domain: "gitlab.example.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &ProvisionTokenV2{
|
||||
Kind: KindToken,
|
||||
Version: V2,
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
Namespace: defaults.Namespace,
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: JoinMethodGitLab,
|
||||
GitLab: &ProvisionTokenSpecV2GitLab{
|
||||
Allow: []*ProvisionTokenSpecV2GitLab_Rule{
|
||||
{
|
||||
Sub: "asub",
|
||||
},
|
||||
},
|
||||
Domain: "gitlab.example.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "invalid overridden domain",
|
||||
token: &ProvisionTokenV2{
|
||||
Metadata: Metadata{
|
||||
Name: "test",
|
||||
},
|
||||
Spec: ProvisionTokenSpecV2{
|
||||
Roles: []SystemRole{RoleNode},
|
||||
JoinMethod: JoinMethodGitLab,
|
||||
GitLab: &ProvisionTokenSpecV2GitLab{
|
||||
Allow: []*ProvisionTokenSpecV2GitLab_Rule{
|
||||
{
|
||||
Sub: "asub",
|
||||
},
|
||||
},
|
||||
Domain: "http://gitlab.example.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: &trace.BadParameterError{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
@@ -459,7 +609,7 @@ func TestProvisionTokenV2_CheckAndSetDefaults(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
if tc.expected != nil {
|
||||
require.Equal(t, tc.token, tc.expected)
|
||||
require.Equal(t, tc.expected, tc.token)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+2332
-1575
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user