Skip to content

Commit

Permalink
added tests for multiple config, roles and tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
ilijamt committed Oct 12, 2024
1 parent 6b5ed49 commit 86782e2
Show file tree
Hide file tree
Showing 11 changed files with 1,292 additions and 18 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ The following data points can be used within your token name template. These are
* access_level
* scopes
* token_type
* role_name
* config_name
* gitlab_revokes_token
* unix_timestamp_utc

Expand Down
4 changes: 2 additions & 2 deletions entry_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type EntryRole struct {
AccessLevel AccessLevel `json:"access_level" structs:"access_level" mapstructure:"access_level,omitempty"`
TokenType TokenType `json:"token_type" structs:"token_type" mapstructure:"token_type"`
GitlabRevokesTokens bool `json:"gitlab_revokes_token" structs:"gitlab_revokes_token" mapstructure:"gitlab_revokes_token"`
Config string `json:"config" structs:"config" mapstructure:"config"`
ConfigName string `json:"config_name" structs:"config_name" mapstructure:"config_name"`
}

func (e EntryRole) LogicalResponseData() map[string]any {
Expand All @@ -30,7 +30,7 @@ func (e EntryRole) LogicalResponseData() map[string]any {
"ttl": int64(e.TTL / time.Second),
"token_type": e.TokenType.String(),
"gitlab_revokes_token": e.GitlabRevokesTokens,
"config": e.Config,
"config_name": e.ConfigName,
}
}

Expand Down
4 changes: 2 additions & 2 deletions path_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (b *Backend) pathConfigDelete(ctx context.Context, req *logical.Request, da

if err = req.Storage.Delete(ctx, fmt.Sprintf("%s/%s", PathConfigStorage, name)); err == nil {
event(ctx, b.Backend, "config-delete", map[string]string{
"path": "config",
"path": fmt.Sprintf("%s/%s", PathConfigStorage, name),
})
b.SetClient(nil, name)
}
Expand Down Expand Up @@ -194,7 +194,7 @@ func (b *Backend) pathConfigWrite(ctx context.Context, req *logical.Request, dat

if err = saveConfig(ctx, *config, req.Storage); err == nil {
event(ctx, b.Backend, "config-write", map[string]string{
"path": "config",
"path": fmt.Sprintf("%s/%s", PathConfigStorage, name),
"auto_rotate_token": strconv.FormatBool(config.AutoRotateToken),
"auto_rotate_before": config.AutoRotateBefore.String(),
"base_url": config.BaseURL,
Expand Down
2 changes: 1 addition & 1 deletion path_config_rotate.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (b *Backend) pathConfigTokenRotate(ctx context.Context, request *logical.Re
}

event(ctx, b.Backend, "config-token-rotate", map[string]string{
"path": "config",
"path": fmt.Sprintf("%s/%s", PathConfigStorage, name),
"expires_at": entryToken.ExpiresAt.Format(time.RFC3339),
"created_at": entryToken.CreatedAt.Format(time.RFC3339),
"scopes": strings.Join(entryToken.Scopes, ", "),
Expand Down
8 changes: 4 additions & 4 deletions path_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ var (
Name: "Gitlab revokes token.",
},
},
"config": {
"config_name": {
Type: framework.TypeString,
Default: TypeConfigDefault,
Required: false,
Expand Down Expand Up @@ -210,7 +210,7 @@ func (b *Backend) pathRolesWrite(ctx context.Context, req *logical.Request, data
var warnings []string
var tokenType TokenType
var accessLevel AccessLevel
var configName = cmp.Or(data.Get("config").(string), TypeConfigDefault)
var configName = cmp.Or(data.Get("config_name").(string), TypeConfigDefault)

b.lockClientMutex.RLock()
defer b.lockClientMutex.RUnlock()
Expand All @@ -235,7 +235,7 @@ func (b *Backend) pathRolesWrite(ctx context.Context, req *logical.Request, data
AccessLevel: accessLevel,
TokenType: tokenType,
GitlabRevokesTokens: data.Get("gitlab_revokes_token").(bool),
Config: configName,
ConfigName: configName,
}

// validate name of the entry role
Expand All @@ -248,7 +248,7 @@ func (b *Backend) pathRolesWrite(ctx context.Context, req *logical.Request, data
err = multierror.Append(err, fmt.Errorf("token_type='%s', should be one of %v: %w", data.Get("token_type").(string), validTokenTypes, ErrFieldInvalidValue))
}

var skipFields = []string{"config"}
var skipFields = []string{"config_name"}

// validate access level
var validAccessLevels []string
Expand Down
10 changes: 5 additions & 5 deletions path_role_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ func TestPathRoles(t *testing.T) {
require.NotNil(t, resp)
require.NoError(t, resp.Error())
require.Empty(t, resp.Warnings)
require.EqualValues(t, resp.Data["config"], gitlab.TypeConfigDefault)
require.EqualValues(t, resp.Data["config_name"], gitlab.TypeConfigDefault)
})
})

Expand Down Expand Up @@ -239,7 +239,7 @@ func TestPathRoles(t *testing.T) {
})
require.NoError(t, err)
require.NotNil(t, resp)
require.EqualValues(t, resp.Data["config"], gitlab.TypeConfigDefault)
require.EqualValues(t, resp.Data["config_name"], gitlab.TypeConfigDefault)
})

t.Run("invalid scopes", func(t *testing.T) {
Expand Down Expand Up @@ -284,7 +284,7 @@ func TestPathRoles(t *testing.T) {
})
require.NoError(t, err)
require.NotNil(t, resp)
require.EqualValues(t, resp.Data["config"], gitlab.TypeConfigDefault)
require.EqualValues(t, resp.Data["config_name"], gitlab.TypeConfigDefault)
})

t.Run("invalid scopes", func(t *testing.T) {
Expand Down Expand Up @@ -329,7 +329,7 @@ func TestPathRoles(t *testing.T) {
})
require.NoError(t, err)
require.NotNil(t, resp)
require.EqualValues(t, resp.Data["config"], gitlab.TypeConfigDefault)
require.EqualValues(t, resp.Data["config_name"], gitlab.TypeConfigDefault)
})

t.Run("invalid scopes", func(t *testing.T) {
Expand Down Expand Up @@ -412,7 +412,7 @@ func TestPathRoles(t *testing.T) {
require.NotNil(t, resp)
require.NoError(t, resp.Error())
require.Empty(t, resp.Warnings)
require.EqualValues(t, resp.Data["config"], gitlab.TypeConfigDefault)
require.EqualValues(t, resp.Data["config_name"], gitlab.TypeConfigDefault)

// read a role
resp, err = b.HandleRequest(ctx, &logical.Request{
Expand Down
4 changes: 2 additions & 2 deletions path_token_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (b *Backend) pathTokenRoleCreate(ctx context.Context, req *logical.Request,

_, expiresAt, _ = calculateGitlabTTL(role.TTL, startTime)

client, err = b.getClient(ctx, req.Storage, role.Config)
client, err = b.getClient(ctx, req.Storage, role.ConfigName)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -114,7 +114,7 @@ func (b *Backend) pathTokenRoleCreate(ctx context.Context, req *logical.Request,
return nil, cmp.Or(err, fmt.Errorf("%w: token is nil", ErrNilValue))
}

token.ConfigName = cmp.Or(role.Config, DefaultConfigName)
token.ConfigName = cmp.Or(role.ConfigName, DefaultConfigName)
token.RoleName = role.RoleName
token.GitlabRevokesToken = role.GitlabRevokesTokens

Expand Down
152 changes: 152 additions & 0 deletions path_token_role_multiple_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package gitlab_test

import (
"context"
"fmt"
"testing"

"github.com/hashicorp/vault/sdk/logical"
"github.com/stretchr/testify/require"
g "github.com/xanzy/go-gitlab"

gitlab "github.com/ilijamt/vault-plugin-secrets-gitlab"
)

func TestPathTokenRolesMultipleConfigs(t *testing.T) {
httpClient, gitlabUrl := getClient(t)
ctx := gitlab.HttpClientNewContext(context.Background(), httpClient)

b, l, events, err := getBackendWithEvents(ctx)
require.NoError(t, err)
require.NoError(t, err)
require.NotNil(t, events)
require.NotNil(t, b)
require.NotNil(t, l)

var configs = map[string]string{"root": "glpat-secret-random-token", "admin": "glpat-secret-admin-token", "normal": "glpat-secret-normal-token"}
for name, token := range configs {
require.NoError(t,
writeBackendConfigWithName(ctx, b, l,
map[string]any{
"token": token,
"base_url": gitlabUrl,
"type": gitlab.TypeSelfManaged.String(),
},
name,
),
)
}

type roleData struct {
rn, path string
tt gitlab.TokenType
al gitlab.AccessLevel
scopes []string
}
var roles = map[string][]roleData{
"root": {
{rn: "root-root", path: "root", tt: gitlab.TokenTypePersonal, scopes: gitlab.ValidPersonalTokenScopes},
{rn: "root-normal-user", path: "normal-user", tt: gitlab.TokenTypePersonal, scopes: gitlab.ValidPersonalTokenScopes},
},
"admin": {
{rn: "admin-example-example", path: "example/example", tt: gitlab.TokenTypeProject, al: gitlab.AccessLevelGuestPermissions, scopes: []string{gitlab.TokenScopeApi.String()}},
},
"normal": {
{rn: "normal-example", path: "example", tt: gitlab.TokenTypeGroup, al: gitlab.AccessLevelGuestPermissions, scopes: []string{gitlab.TokenScopeApi.String()}},
},
}

for cfg, rds := range roles {
for _, rd := range rds {
var data = map[string]any{
"name": fmt.Sprintf("%s-{{ .role_name }}-{{ .config_name }}-{{ .token_type }}", rd.path),
"token_type": rd.tt.String(), "path": rd.path, "config_name": cfg, "ttl": gitlab.DefaultAccessTokenMinTTL,
}

switch rd.tt {
case gitlab.TokenTypePersonal:
data["access_level"] = rd.al.String()
data["scopes"] = rd.scopes
case gitlab.TokenTypeGroup:
data["access_level"] = rd.al.String()
data["scopes"] = rd.scopes
case gitlab.TokenTypeProject:
data["access_level"] = rd.al.String()
data["scopes"] = rd.scopes
}

resp, err := b.HandleRequest(ctx, &logical.Request{
Operation: logical.CreateOperation,
Path: fmt.Sprintf("%s/%s", gitlab.PathRoleStorage, rd.rn), Storage: l,
Data: data,
})
require.NoError(t, err)
require.NotNil(t, resp)
require.NoError(t, resp.Error())
require.Empty(t, resp.Warnings)
require.EqualValues(t, cfg, resp.Data["config_name"])

resp, err = b.HandleRequest(ctx, &logical.Request{
Operation: logical.ReadOperation, Storage: l,
Path: fmt.Sprintf("%s/%s", gitlab.PathTokenRoleStorage, rd.rn),
})
require.NoError(t, err)
require.NotNil(t, resp)
require.NotNil(t, resp.Secret)
require.NoError(t, resp.Error())

var token = resp.Data["token"].(string)
require.NotEmpty(t, token)
var secret = resp.Secret
require.NotNil(t, secret)

// verify token that it works
var c *g.Client
c, err = g.NewClient(token, g.WithHTTPClient(httpClient), g.WithBaseURL(gitlabUrl))
require.NoError(t, err)
require.NotNil(t, c)

pat, r, err := c.PersonalAccessTokens.GetSinglePersonalAccessToken()
require.NoError(t, err)
require.NotNil(t, r)
require.NotNil(t, pat)

resp, err = b.HandleRequest(ctx, &logical.Request{
Operation: logical.RevokeOperation,
Path: "/",
Storage: l,
Secret: secret,
})
require.NoError(t, err)
require.Nil(t, resp)

}
}

resp, err := b.HandleRequest(ctx, &logical.Request{
Operation: logical.ListOperation,
Path: gitlab.PathRoleStorage, Storage: l,
})
require.NoError(t, err)
require.NotNil(t, resp)
require.NoError(t, resp.Error())
require.NotEmpty(t, resp.Data)

events.expectEvents(t, []expectedEvent{
{eventType: "gitlab/config-write"},
{eventType: "gitlab/config-write"},
{eventType: "gitlab/config-write"},
{eventType: "gitlab/role-write"},
{eventType: "gitlab/token-write"},
{eventType: "gitlab/token-revoke"},
{eventType: "gitlab/role-write"},
{eventType: "gitlab/token-write"},
{eventType: "gitlab/token-revoke"},
{eventType: "gitlab/role-write"},
{eventType: "gitlab/token-write"},
{eventType: "gitlab/token-revoke"},
{eventType: "gitlab/role-write"},
{eventType: "gitlab/token-write"},
{eventType: "gitlab/token-revoke"},
})
}
Loading

0 comments on commit 86782e2

Please sign in to comment.