diff --git a/backend.go b/backend.go index d15f5e2..d84bdca 100644 --- a/backend.go +++ b/backend.go @@ -15,6 +15,7 @@ import ( "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/flags" g "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" + config2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) @@ -107,7 +108,7 @@ func (b *Backend) periodicFunc(ctx context.Context, req *logical.Request) (err e b.Logger().Debug("Periodic action executing") if b.WriteSafeReplicationState() { - var config *EntryConfig + var config *config2.EntryConfig b.lockClientMutex.Lock() unlockLockClientMutex := sync.OnceFunc(func() { b.lockClientMutex.Unlock() }) @@ -176,7 +177,7 @@ func (b *Backend) getClient(ctx context.Context, s logical.Storage, name string) b.lockClientMutex.RLock() defer b.lockClientMutex.RUnlock() - var config *EntryConfig + var config *config2.EntryConfig config, err = getConfig(ctx, s, name) if err != nil { b.Logger().Error("Failed to retrieve configuration", "error", err.Error()) diff --git a/defs.go b/defs.go index f2d116f..ec35757 100644 --- a/defs.go +++ b/defs.go @@ -2,15 +2,15 @@ package gitlab import ( "time" + + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" ) const ( DefaultConfigFieldAccessTokenMaxTTL = 7 * 24 * time.Hour - DefaultConfigFieldAccessTokenRotate = DefaultAutoRotateBeforeMinTTL + DefaultConfigFieldAccessTokenRotate = config.DefaultAutoRotateBeforeMinTTL DefaultRoleFieldAccessTokenMaxTTL = 24 * time.Hour DefaultAccessTokenMinTTL = 24 * time.Hour DefaultAccessTokenMaxPossibleTTL = 365 * 24 * time.Hour - DefaultAutoRotateBeforeMinTTL = 24 * time.Hour - DefaultAutoRotateBeforeMaxTTL = 730 * time.Hour DefaultConfigName = "default" ) diff --git a/gitlab_client.go b/gitlab_client.go index 913295a..e2757d0 100644 --- a/gitlab_client.go +++ b/gitlab_client.go @@ -16,7 +16,8 @@ import ( "golang.org/x/time/rate" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + config2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" + modelToken "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" t "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) @@ -29,7 +30,7 @@ var ( type gitlabClient struct { client *g.Client httpClient *http.Client - config *EntryConfig + config *config2.EntryConfig logger hclog.Logger } @@ -47,7 +48,7 @@ func (gc *gitlabClient) GetProjectIdByPath(ctx context.Context, path string) (pr return projectId, err } -func (gc *gitlabClient) CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *models.TokenGroupDeploy, err error) { +func (gc *gitlabClient) CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *modelToken.TokenGroupDeploy, err error) { var dt *g.DeployToken defer func() { gc.logger.Debug("Create group deploy token", "groupId", groupId, "name", name, "path", path, "expiresAt", expiresAt, "scopes", scopes, "error", err) @@ -62,9 +63,9 @@ func (gc *gitlabClient) CreateGroupDeployToken(ctx context.Context, path string, }, g.WithContext(ctx), ); err == nil { - et = &models.TokenGroupDeploy{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + et = &modelToken.TokenGroupDeploy{ + TokenWithScopes: modelToken.TokenWithScopes{ + Token: modelToken.Token{ TokenID: dt.ID, ParentID: strconv.Itoa(groupId), Path: path, @@ -81,7 +82,7 @@ func (gc *gitlabClient) CreateGroupDeployToken(ctx context.Context, path string, return et, err } -func (gc *gitlabClient) CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *models.TokenProjectDeploy, err error) { +func (gc *gitlabClient) CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *modelToken.TokenProjectDeploy, err error) { var dt *g.DeployToken defer func() { gc.logger.Debug("Create project deploy token", "projectId", projectId, "name", name, "path", path, "expiresAt", expiresAt, "scopes", scopes, "error", err) @@ -95,9 +96,9 @@ func (gc *gitlabClient) CreateProjectDeployToken(ctx context.Context, path strin }, g.WithContext(ctx), ); err == nil { - et = &models.TokenProjectDeploy{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + et = &modelToken.TokenProjectDeploy{ + TokenWithScopes: modelToken.TokenWithScopes{ + Token: modelToken.Token{ TokenID: dt.ID, ParentID: strconv.Itoa(projectId), Path: path, @@ -141,7 +142,7 @@ func (gc *gitlabClient) Metadata(ctx context.Context) (metadata *g.Metadata, err return metadata, err } -func (gc *gitlabClient) CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (et *models.TokenPipelineProjectTrigger, err error) { +func (gc *gitlabClient) CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (et *modelToken.TokenPipelineProjectTrigger, err error) { var pt *g.PipelineTrigger defer func() { gc.logger.Debug("Create a pipeline project trigger access token", "path", path, "name", name, "projectId", description, "description", "error", err) @@ -152,8 +153,8 @@ func (gc *gitlabClient) CreatePipelineProjectTriggerAccessToken(ctx context.Cont &g.AddPipelineTriggerOptions{Description: &description}, g.WithContext(ctx), ); err == nil { - et = &models.TokenPipelineProjectTrigger{ - Token: models.Token{ + et = &modelToken.TokenPipelineProjectTrigger{ + Token: modelToken.Token{ TokenID: pt.ID, ParentID: strconv.Itoa(projectId), Path: path, @@ -203,7 +204,7 @@ func (gc *gitlabClient) GitlabClient(ctx context.Context) *g.Client { return gc.client } -func (gc *gitlabClient) CreateGroupServiceAccountAccessToken(ctx context.Context, path string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (et *models.TokenGroupServiceAccount, err error) { +func (gc *gitlabClient) CreateGroupServiceAccountAccessToken(ctx context.Context, path string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (et *modelToken.TokenGroupServiceAccount, err error) { var at *g.PersonalAccessToken defer func() { gc.logger.Debug("Create group service access token", "pat", at, "et", et, "path", path, "groupId", groupId, "userId", userId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "error", err) @@ -214,9 +215,9 @@ func (gc *gitlabClient) CreateGroupServiceAccountAccessToken(ctx context.Context Scopes: &scopes, }, g.WithContext(ctx)) if err == nil { - et = &models.TokenGroupServiceAccount{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + et = &modelToken.TokenGroupServiceAccount{ + TokenWithScopes: modelToken.TokenWithScopes{ + Token: modelToken.Token{ TokenID: at.ID, ParentID: groupId, Path: path, @@ -234,16 +235,16 @@ func (gc *gitlabClient) CreateGroupServiceAccountAccessToken(ctx context.Context return et, err } -func (gc *gitlabClient) CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (et *models.TokenUserServiceAccount, err error) { +func (gc *gitlabClient) CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (et *modelToken.TokenUserServiceAccount, err error) { defer func() { gc.logger.Debug("Create user service access token", "et", et, "username", username, "userId", userId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "error", err) }() - var etp *models.TokenPersonal + var etp *modelToken.TokenPersonal etp, err = gc.CreatePersonalAccessToken(ctx, username, userId, name, expiresAt, scopes) if err == nil && etp != nil { - et = &models.TokenUserServiceAccount{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + et = &modelToken.TokenUserServiceAccount{ + TokenWithScopes: modelToken.TokenWithScopes{ + Token: modelToken.Token{ TokenID: etp.TokenID, ParentID: etp.ParentID, Path: etp.Path, @@ -268,7 +269,7 @@ func (gc *gitlabClient) RevokeUserServiceAccountAccessToken(ctx context.Context, } var c *g.Client - if c, err = newGitlabClient(&EntryConfig{ + if c, err = newGitlabClient(&config2.EntryConfig{ BaseURL: gc.config.BaseURL, Token: token, }, gc.httpClient); err == nil { @@ -286,7 +287,7 @@ func (gc *gitlabClient) RevokeGroupServiceAccountAccessToken(ctx context.Context } var c *g.Client - if c, err = newGitlabClient(&EntryConfig{ + if c, err = newGitlabClient(&config2.EntryConfig{ BaseURL: gc.config.BaseURL, Token: token, }, gc.httpClient); err == nil { @@ -296,13 +297,13 @@ func (gc *gitlabClient) RevokeGroupServiceAccountAccessToken(ctx context.Context return err } -func (gc *gitlabClient) CurrentTokenInfo(ctx context.Context) (et *models.TokenConfig, err error) { +func (gc *gitlabClient) CurrentTokenInfo(ctx context.Context) (et *modelToken.TokenConfig, err error) { var pat *g.PersonalAccessToken defer func() { gc.logger.Debug("Current token info", "token", et, "error", err) }() if pat, _, err = gc.client.PersonalAccessTokens.GetSinglePersonalAccessToken(g.WithContext(ctx)); err == nil { - et = &models.TokenConfig{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + et = &modelToken.TokenConfig{ + TokenWithScopes: modelToken.TokenWithScopes{ + Token: modelToken.Token{ TokenID: pat.ID, Name: pat.Name, Token: pat.Token, @@ -325,7 +326,7 @@ func (gc *gitlabClient) CurrentTokenInfo(ctx context.Context) (et *models.TokenC return et, err } -func (gc *gitlabClient) RotateCurrentToken(ctx context.Context) (token *models.TokenConfig, currentEntryToken *models.TokenConfig, err error) { +func (gc *gitlabClient) RotateCurrentToken(ctx context.Context) (token *modelToken.TokenConfig, currentEntryToken *modelToken.TokenConfig, err error) { var expiresAt time.Time defer func() { gc.logger.Debug("Rotate current token", "token", token, "currentEntryToken", currentEntryToken, "expiresAt", expiresAt, "error", err) @@ -354,9 +355,9 @@ func (gc *gitlabClient) RotateCurrentToken(ctx context.Context) (token *models.T return nil, nil, err } - token = &models.TokenConfig{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + token = &modelToken.TokenConfig{ + TokenWithScopes: modelToken.TokenWithScopes{ + Token: modelToken.Token{ TokenID: pat.ID, ParentID: "", Path: usr.Username, @@ -405,7 +406,7 @@ func (gc *gitlabClient) GetUserIdByUsername(ctx context.Context, username string return userId, nil } -func (gc *gitlabClient) CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (et *models.TokenPersonal, err error) { +func (gc *gitlabClient) CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (et *modelToken.TokenPersonal, err error) { var at *g.PersonalAccessToken defer func() { gc.logger.Debug("Create personal access token", "pat", at, "et", et, "username", username, "userId", userId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "error", err) @@ -415,9 +416,9 @@ func (gc *gitlabClient) CreatePersonalAccessToken(ctx context.Context, username ExpiresAt: (*g.ISOTime)(&expiresAt), Scopes: &scopes, }, g.WithContext(ctx)); err == nil { - et = &models.TokenPersonal{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + et = &modelToken.TokenPersonal{ + TokenWithScopes: modelToken.TokenWithScopes{ + Token: modelToken.Token{ TokenID: at.ID, Path: username, Name: name, @@ -434,7 +435,7 @@ func (gc *gitlabClient) CreatePersonalAccessToken(ctx context.Context, username return et, err } -func (gc *gitlabClient) CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (et *models.TokenGroup, err error) { +func (gc *gitlabClient) CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (et *modelToken.TokenGroup, err error) { var at *g.GroupAccessToken defer func() { gc.logger.Debug("Create group access token", "gat", at, "et", et, "groupId", groupId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "accessLevel", accessLevel, "error", err) @@ -447,9 +448,9 @@ func (gc *gitlabClient) CreateGroupAccessToken(ctx context.Context, groupId stri ExpiresAt: (*g.ISOTime)(&expiresAt), AccessLevel: al, }, g.WithContext(ctx)); err == nil { - et = &models.TokenGroup{ - TokenWithScopesAndAccessLevel: models.TokenWithScopesAndAccessLevel{ - Token: models.Token{ + et = &modelToken.TokenGroup{ + TokenWithScopesAndAccessLevel: modelToken.TokenWithScopesAndAccessLevel{ + Token: modelToken.Token{ TokenID: at.ID, ParentID: groupId, Path: groupId, @@ -467,7 +468,7 @@ func (gc *gitlabClient) CreateGroupAccessToken(ctx context.Context, groupId stri return et, err } -func (gc *gitlabClient) CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (et *models.TokenProject, err error) { +func (gc *gitlabClient) CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (et *modelToken.TokenProject, err error) { var at *g.ProjectAccessToken defer func() { gc.logger.Debug("Create project access token", "gat", at, "et", et, "projectId", projectId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "accessLevel", accessLevel, "error", err) @@ -480,9 +481,9 @@ func (gc *gitlabClient) CreateProjectAccessToken(ctx context.Context, projectId ExpiresAt: (*g.ISOTime)(&expiresAt), AccessLevel: al, }, g.WithContext(ctx)); err == nil { - et = &models.TokenProject{ - TokenWithScopesAndAccessLevel: models.TokenWithScopesAndAccessLevel{ - Token: models.Token{ + et = &modelToken.TokenProject{ + TokenWithScopesAndAccessLevel: modelToken.TokenWithScopesAndAccessLevel{ + Token: modelToken.Token{ TokenID: at.ID, ParentID: projectId, Path: projectId, @@ -551,7 +552,7 @@ func (gc *gitlabClient) Valid(ctx context.Context) bool { var _ Client = new(gitlabClient) -func newGitlabClient(config *EntryConfig, httpClient *http.Client) (gc *g.Client, err error) { +func newGitlabClient(config *config2.EntryConfig, httpClient *http.Client) (gc *g.Client, err error) { if strings.TrimSpace(config.BaseURL) == "" { err = errors.Join(err, fmt.Errorf("gitlab base url: %w", errs.ErrInvalidValue)) } @@ -576,7 +577,7 @@ func newGitlabClient(config *EntryConfig, httpClient *http.Client) (gc *g.Client return g.NewClient(config.Token, opts...) } -func NewGitlabClient(config *EntryConfig, httpClient *http.Client, logger hclog.Logger) (client Client, err error) { +func NewGitlabClient(config *config2.EntryConfig, httpClient *http.Client, logger hclog.Logger) (client Client, err error) { if config == nil { return nil, fmt.Errorf("configure the backend first, config: %w", errs.ErrNilValue) } diff --git a/gitlab_client_iface.go b/gitlab_client_iface.go index 76adf0e..d0974f1 100644 --- a/gitlab_client_iface.go +++ b/gitlab_client_iface.go @@ -6,7 +6,7 @@ import ( g "gitlab.com/gitlab-org/api/client-go" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" t "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" ) @@ -14,25 +14,25 @@ type Client interface { GitlabClient(ctx context.Context) *g.Client Valid(ctx context.Context) bool Metadata(ctx context.Context) (*g.Metadata, error) - CurrentTokenInfo(ctx context.Context) (*models.TokenConfig, error) - RotateCurrentToken(ctx context.Context) (newToken *models.TokenConfig, oldToken *models.TokenConfig, err error) - CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*models.TokenPersonal, error) - CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*models.TokenGroup, error) - CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*models.TokenProject, error) + CurrentTokenInfo(ctx context.Context) (*token.TokenConfig, error) + RotateCurrentToken(ctx context.Context) (newToken *token.TokenConfig, oldToken *token.TokenConfig, err error) + CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*token.TokenPersonal, error) + CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*token.TokenGroup, error) + CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*token.TokenProject, error) RevokePersonalAccessToken(ctx context.Context, tokenId int) error RevokeProjectAccessToken(ctx context.Context, tokenId int, projectId string) error RevokeGroupAccessToken(ctx context.Context, tokenId int, groupId string) error GetUserIdByUsername(ctx context.Context, username string) (int, error) GetGroupIdByPath(ctx context.Context, path string) (int, error) GetProjectIdByPath(ctx context.Context, path string) (int, error) - CreateGroupServiceAccountAccessToken(ctx context.Context, group string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*models.TokenGroupServiceAccount, error) - CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*models.TokenUserServiceAccount, error) + CreateGroupServiceAccountAccessToken(ctx context.Context, group string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*token.TokenGroupServiceAccount, error) + CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*token.TokenUserServiceAccount, error) RevokeUserServiceAccountAccessToken(ctx context.Context, token string) error RevokeGroupServiceAccountAccessToken(ctx context.Context, token string) error - CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (*models.TokenPipelineProjectTrigger, error) + CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (*token.TokenPipelineProjectTrigger, error) RevokePipelineProjectTriggerAccessToken(ctx context.Context, projectId int, tokenId int) error - CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *models.TokenProjectDeploy, err error) + CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *token.TokenProjectDeploy, err error) RevokeProjectDeployToken(ctx context.Context, projectId, deployTokenId int) (err error) - CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *models.TokenGroupDeploy, err error) + CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *token.TokenGroupDeploy, err error) RevokeGroupDeployToken(ctx context.Context, groupId, deployTokenId int) (err error) } diff --git a/gitlab_client_test.go b/gitlab_client_test.go index 365d64a..f03b980 100644 --- a/gitlab_client_test.go +++ b/gitlab_client_test.go @@ -14,6 +14,7 @@ import ( gitlab "github.com/ilijamt/vault-plugin-secrets-gitlab" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" token2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" ) @@ -25,19 +26,19 @@ func TestGitlabClient(t *testing.T) { }) t.Run("no token", func(t *testing.T) { - var client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{}, nil, nil) + var client, err = gitlab.NewGitlabClient(&config.EntryConfig{}, nil, nil) require.ErrorIs(t, err, errs.ErrInvalidValue) require.Nil(t, client) }) t.Run("no base url", func(t *testing.T) { - var client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{}, nil, nil) + var client, err = gitlab.NewGitlabClient(&config.EntryConfig{}, nil, nil) require.ErrorIs(t, err, errs.ErrInvalidValue) require.Nil(t, client) }) t.Run("with http client", func(t *testing.T) { - var client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + var client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: "token", BaseURL: "https://example.com", }, &http.Client{}, nil) @@ -47,7 +48,7 @@ func TestGitlabClient(t *testing.T) { t.Run("revoke service account token with empty token", func(t *testing.T) { var ctx = t.Context() - var client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + var client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: "token", BaseURL: "https://example.com", }, &http.Client{}, nil) @@ -64,7 +65,7 @@ func TestGitlabClient_InvalidToken(t *testing.T) { var err error httpClient, url := getClient(t, "unit") var client gitlab.Client - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: tokenName, BaseURL: url, }, httpClient, nil) @@ -107,7 +108,7 @@ func TestGitlabClient_RevokeToken_NotFound(t *testing.T) { var err error httpClient, url := getClient(t, "unit") var client gitlab.Client - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: getGitlabToken("admin_user_root").Token, BaseURL: url, }, httpClient, nil) @@ -127,7 +128,7 @@ func TestGitlabClient_GetGroupIdByPath(t *testing.T) { var tokenName = "admin_user_root" httpClient, url := getClient(t, "unit") var client gitlab.Client - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: getGitlabToken(tokenName).Token, BaseURL: url, }, httpClient, nil) @@ -148,7 +149,7 @@ func TestGitlabClient_GetUserIdByUsername(t *testing.T) { var err error httpClient, url := getClient(t, "unit") var client gitlab.Client - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: getGitlabToken("admin_user_root").Token, BaseURL: url, }, httpClient, nil) @@ -166,7 +167,7 @@ func TestGitlabClient_GetUserIdByUsernameDoesNotMatch(t *testing.T) { var ctx = t.Context() httpClient, url := getClient(t, "unit") var client gitlab.Client - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: getGitlabToken("admin_user_root").Token, BaseURL: url, }, httpClient, nil) @@ -188,7 +189,7 @@ func TestGitlabClient_Revoke_NonExistingTokens(t *testing.T) { var err error httpClient, url := getClient(t, "unit") var client gitlab.Client - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: getGitlabToken("admin_user_root").Token, BaseURL: url, }, httpClient, nil) @@ -206,7 +207,7 @@ func TestGitlabClient_CurrentTokenInfo(t *testing.T) { var ctx = t.Context() httpClient, url := getClient(t, "unit") var client gitlab.Client - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: getGitlabToken("admin_user_root").Token, BaseURL: url, }, httpClient, nil) @@ -225,7 +226,7 @@ func TestGitlabClient_Metadata(t *testing.T) { var ctx = t.Context() httpClient, url := getClient(t, "unit") var client gitlab.Client - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: getGitlabToken("admin_user_root").Token, BaseURL: url, }, httpClient, nil) @@ -244,7 +245,7 @@ func TestGitlabClient_CreateAccessToken_And_Revoke(t *testing.T) { ctx, timeExpiresAt := ctxTestTime(t.Context(), t.Name(), tokenName) httpClient, url := getClient(t, "unit") var client gitlab.Client - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: getGitlabToken(tokenName).Token, BaseURL: url, }, httpClient, nil) @@ -301,7 +302,7 @@ func TestGitlabClient_RotateCurrentToken(t *testing.T) { httpClient, url := getClient(t, "unit") var client gitlab.Client var tokenName = "admin_user_auto_rotate_token_1" - client, err = gitlab.NewGitlabClient(&gitlab.EntryConfig{ + client, err = gitlab.NewGitlabClient(&config.EntryConfig{ Token: getGitlabToken(tokenName).Token, BaseURL: url, }, httpClient, logging.NewVaultLoggerWithWriter(io.Discard, log.Trace)) diff --git a/helpers.go b/helpers.go new file mode 100644 index 0000000..e258166 --- /dev/null +++ b/helpers.go @@ -0,0 +1,24 @@ +package gitlab + +import ( + "context" + "fmt" + + "github.com/hashicorp/vault/sdk/logical" + + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/role" +) + +func getConfig(ctx context.Context, s logical.Storage, name string) (cfg *config.EntryConfig, err error) { + return model.Get[config.EntryConfig](ctx, s, fmt.Sprintf("%s/%s", PathConfigStorage, name)) +} + +func saveConfig(ctx context.Context, config *config.EntryConfig, s logical.Storage) error { + return model.Save(ctx, s, PathConfigStorage, config) +} + +func getRole(ctx context.Context, name string, s logical.Storage) (r *role.Role, err error) { + return model.Get[role.Role](ctx, s, fmt.Sprintf("%s/%s", PathRoleStorage, name)) +} diff --git a/helpers_test.go b/helpers_test.go index f093a4d..6ca4b0c 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -20,7 +20,6 @@ import ( "github.com/google/uuid" log "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-multierror" "github.com/hashicorp/vault/sdk/helper/logging" "github.com/hashicorp/vault/sdk/logical" "github.com/stretchr/testify/require" @@ -28,7 +27,7 @@ import ( gitlab "github.com/ilijamt/vault-plugin-secrets-gitlab" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/flags" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" t "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) @@ -42,20 +41,6 @@ var ( gitlabServiceAccountToken = cmp.Or(os.Getenv("GITLAB_SERVICE_ACCOUNT_TOKEN"), "REPLACED-TOKEN") ) -func countErrByName(err *multierror.Error) map[string]int { - var data = make(map[string]int) - - for _, e := range err.Errors { - name := errors.Unwrap(e).Error() - if _, ok := data[name]; !ok { - data[name] = 0 - } - data[name]++ - } - - return data -} - type expectedEvent struct { eventType string } @@ -157,17 +142,17 @@ func newInMemoryClient(valid bool) *inMemoryClient { valid: valid, accessTokens: make(map[string]t.Token), - mainTokenInfo: models.TokenConfig{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + mainTokenInfo: token.TokenConfig{ + TokenWithScopes: token.TokenWithScopes{ + Token: token.Token{ CreatedAt: g.Ptr(time.Now()), ExpiresAt: g.Ptr(time.Now()), }, }, }, - rotateMainToken: models.TokenConfig{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + rotateMainToken: token.TokenConfig{ + TokenWithScopes: token.TokenWithScopes{ + Token: token.Token{ CreatedAt: g.Ptr(time.Now()), ExpiresAt: g.Ptr(time.Now()), }, @@ -206,8 +191,8 @@ type inMemoryClient struct { calledRotateMainToken int calledValid int - mainTokenInfo models.TokenConfig - rotateMainToken models.TokenConfig + mainTokenInfo token.TokenConfig + rotateMainToken token.TokenConfig accessTokens map[string]t.Token @@ -221,7 +206,7 @@ func (i *inMemoryClient) GetProjectIdByPath(ctx context.Context, path string) (i return i.valueGetProjectIdByPath, nil } -func (i *inMemoryClient) CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *models.TokenProjectDeploy, err error) { +func (i *inMemoryClient) CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *token.TokenProjectDeploy, err error) { i.muLock.Lock() defer i.muLock.Unlock() if i.createProjectDeployTokenError { @@ -230,9 +215,9 @@ func (i *inMemoryClient) CreateProjectDeployToken(ctx context.Context, path stri i.internalCounter++ var tokenId = i.internalCounter key := fmt.Sprintf("%s_%v_%v", t.TypeProjectDeploy.String(), projectId, tokenId) - var entryToken = &models.TokenProjectDeploy{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + var entryToken = &token.TokenProjectDeploy{ + TokenWithScopes: token.TokenWithScopes{ + Token: token.Token{ TokenID: tokenId, ParentID: strconv.Itoa(projectId), Path: path, @@ -249,7 +234,7 @@ func (i *inMemoryClient) CreateProjectDeployToken(ctx context.Context, path stri return entryToken, nil } -func (i *inMemoryClient) CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *models.TokenGroupDeploy, err error) { +func (i *inMemoryClient) CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *token.TokenGroupDeploy, err error) { i.muLock.Lock() defer i.muLock.Unlock() if i.createGroupDeployTokenError { @@ -258,9 +243,9 @@ func (i *inMemoryClient) CreateGroupDeployToken(ctx context.Context, path string i.internalCounter++ var tokenId = i.internalCounter key := fmt.Sprintf("%s_%v_%v", t.TypeGroupDeploy.String(), groupId, tokenId) - var entryToken = &models.TokenGroupDeploy{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + var entryToken = &token.TokenGroupDeploy{ + TokenWithScopes: token.TokenWithScopes{ + Token: token.Token{ TokenID: tokenId, ParentID: strconv.Itoa(groupId), Path: path, @@ -311,7 +296,7 @@ func (i *inMemoryClient) Metadata(ctx context.Context) (*g.Metadata, error) { }, nil } -func (i *inMemoryClient) CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (et *models.TokenPipelineProjectTrigger, err error) { +func (i *inMemoryClient) CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (et *token.TokenPipelineProjectTrigger, err error) { i.muLock.Lock() defer i.muLock.Unlock() if i.createPipelineProjectTriggerAccessTokenError { @@ -320,8 +305,8 @@ func (i *inMemoryClient) CreatePipelineProjectTriggerAccessToken(ctx context.Con i.internalCounter++ var tokenId = i.internalCounter key := fmt.Sprintf("%s_%v_%v", t.TypePipelineProjectTrigger.String(), projectId, tokenId) - var entryToken = &models.TokenPipelineProjectTrigger{ - Token: models.Token{ + var entryToken = &token.TokenPipelineProjectTrigger{ + Token: token.Token{ TokenID: tokenId, ParentID: strconv.Itoa(projectId), Path: strconv.Itoa(projectId), @@ -360,7 +345,7 @@ func (i *inMemoryClient) GitlabClient(ctx context.Context) *g.Client { return nil } -func (i *inMemoryClient) CreateGroupServiceAccountAccessToken(ctx context.Context, path string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*models.TokenGroupServiceAccount, error) { +func (i *inMemoryClient) CreateGroupServiceAccountAccessToken(ctx context.Context, path string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*token.TokenGroupServiceAccount, error) { i.muLock.Lock() defer i.muLock.Unlock() if i.createGroupServiceAccountAccessTokenError { @@ -369,20 +354,20 @@ func (i *inMemoryClient) CreateGroupServiceAccountAccessToken(ctx context.Contex return nil, nil } -func (i *inMemoryClient) CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*models.TokenUserServiceAccount, error) { +func (i *inMemoryClient) CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*token.TokenUserServiceAccount, error) { i.muLock.Lock() if i.createUserServiceAccountAccessTokenError { i.muLock.Unlock() return nil, fmt.Errorf("CreateUserServiceAccountAccessToken") } i.muLock.Unlock() - var tok *models.TokenUserServiceAccount + var tok *token.TokenUserServiceAccount var err error - var cpat *models.TokenPersonal + var cpat *token.TokenPersonal if cpat, err = i.CreatePersonalAccessToken(ctx, username, userId, name, expiresAt, scopes); err != nil && cpat != nil { - tok = &models.TokenUserServiceAccount{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + tok = &token.TokenUserServiceAccount{ + TokenWithScopes: token.TokenWithScopes{ + Token: token.Token{ CreatedAt: cpat.CreatedAt, ExpiresAt: cpat.ExpiresAt, TokenType: t.TypeUserServiceAccount, @@ -420,14 +405,14 @@ func (i *inMemoryClient) RevokeGroupServiceAccountAccessToken(ctx context.Contex return nil } -func (i *inMemoryClient) CurrentTokenInfo(ctx context.Context) (*models.TokenConfig, error) { +func (i *inMemoryClient) CurrentTokenInfo(ctx context.Context) (*token.TokenConfig, error) { i.muLock.Lock() defer i.muLock.Unlock() i.calledMainToken++ return &i.mainTokenInfo, nil } -func (i *inMemoryClient) RotateCurrentToken(ctx context.Context) (*models.TokenConfig, *models.TokenConfig, error) { +func (i *inMemoryClient) RotateCurrentToken(ctx context.Context) (*token.TokenConfig, *token.TokenConfig, error) { i.muLock.Lock() defer i.muLock.Unlock() i.calledRotateMainToken++ @@ -441,7 +426,7 @@ func (i *inMemoryClient) Valid(ctx context.Context) bool { return i.valid } -func (i *inMemoryClient) CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*models.TokenPersonal, error) { +func (i *inMemoryClient) CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*token.TokenPersonal, error) { i.muLock.Lock() defer i.muLock.Unlock() if i.personalAccessTokenCreateError { @@ -449,9 +434,9 @@ func (i *inMemoryClient) CreatePersonalAccessToken(ctx context.Context, username } i.internalCounter++ var tokenId = i.internalCounter - var entryToken = &models.TokenPersonal{ - TokenWithScopes: models.TokenWithScopes{ - Token: models.Token{ + var entryToken = &token.TokenPersonal{ + TokenWithScopes: token.TokenWithScopes{ + Token: token.Token{ TokenID: tokenId, ParentID: "", Path: username, @@ -469,7 +454,7 @@ func (i *inMemoryClient) CreatePersonalAccessToken(ctx context.Context, username return entryToken, nil } -func (i *inMemoryClient) CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*models.TokenGroup, error) { +func (i *inMemoryClient) CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*token.TokenGroup, error) { i.muLock.Lock() defer i.muLock.Unlock() if i.groupAccessTokenCreateError { @@ -477,9 +462,9 @@ func (i *inMemoryClient) CreateGroupAccessToken(ctx context.Context, groupId str } i.internalCounter++ var tokenId = i.internalCounter - var entryToken = &models.TokenGroup{ - TokenWithScopesAndAccessLevel: models.TokenWithScopesAndAccessLevel{ - Token: models.Token{ + var entryToken = &token.TokenGroup{ + TokenWithScopesAndAccessLevel: token.TokenWithScopesAndAccessLevel{ + Token: token.Token{ TokenID: tokenId, ParentID: groupId, Path: groupId, @@ -497,7 +482,7 @@ func (i *inMemoryClient) CreateGroupAccessToken(ctx context.Context, groupId str return entryToken, nil } -func (i *inMemoryClient) CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*models.TokenProject, error) { +func (i *inMemoryClient) CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*token.TokenProject, error) { i.muLock.Lock() defer i.muLock.Unlock() if i.projectAccessTokenCreateError { @@ -505,9 +490,9 @@ func (i *inMemoryClient) CreateProjectAccessToken(ctx context.Context, projectId } i.internalCounter++ var tokenId = i.internalCounter - var entryToken = &models.TokenProject{ - TokenWithScopesAndAccessLevel: models.TokenWithScopesAndAccessLevel{ - Token: models.Token{ + var entryToken = &token.TokenProject{ + TokenWithScopesAndAccessLevel: token.TokenWithScopesAndAccessLevel{ + Token: token.Token{ Token: fmt.Sprintf("glpat-%s", uuid.New().String()), TokenType: t.TypeProject, CreatedAt: g.Ptr(time.Now()), diff --git a/internal/gitlab/client.go b/internal/gitlab/client.go index 76adf0e..d0974f1 100644 --- a/internal/gitlab/client.go +++ b/internal/gitlab/client.go @@ -6,7 +6,7 @@ import ( g "gitlab.com/gitlab-org/api/client-go" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" t "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" ) @@ -14,25 +14,25 @@ type Client interface { GitlabClient(ctx context.Context) *g.Client Valid(ctx context.Context) bool Metadata(ctx context.Context) (*g.Metadata, error) - CurrentTokenInfo(ctx context.Context) (*models.TokenConfig, error) - RotateCurrentToken(ctx context.Context) (newToken *models.TokenConfig, oldToken *models.TokenConfig, err error) - CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*models.TokenPersonal, error) - CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*models.TokenGroup, error) - CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*models.TokenProject, error) + CurrentTokenInfo(ctx context.Context) (*token.TokenConfig, error) + RotateCurrentToken(ctx context.Context) (newToken *token.TokenConfig, oldToken *token.TokenConfig, err error) + CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*token.TokenPersonal, error) + CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*token.TokenGroup, error) + CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel t.AccessLevel) (*token.TokenProject, error) RevokePersonalAccessToken(ctx context.Context, tokenId int) error RevokeProjectAccessToken(ctx context.Context, tokenId int, projectId string) error RevokeGroupAccessToken(ctx context.Context, tokenId int, groupId string) error GetUserIdByUsername(ctx context.Context, username string) (int, error) GetGroupIdByPath(ctx context.Context, path string) (int, error) GetProjectIdByPath(ctx context.Context, path string) (int, error) - CreateGroupServiceAccountAccessToken(ctx context.Context, group string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*models.TokenGroupServiceAccount, error) - CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*models.TokenUserServiceAccount, error) + CreateGroupServiceAccountAccessToken(ctx context.Context, group string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*token.TokenGroupServiceAccount, error) + CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*token.TokenUserServiceAccount, error) RevokeUserServiceAccountAccessToken(ctx context.Context, token string) error RevokeGroupServiceAccountAccessToken(ctx context.Context, token string) error - CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (*models.TokenPipelineProjectTrigger, error) + CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (*token.TokenPipelineProjectTrigger, error) RevokePipelineProjectTriggerAccessToken(ctx context.Context, projectId int, tokenId int) error - CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *models.TokenProjectDeploy, err error) + CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *token.TokenProjectDeploy, err error) RevokeProjectDeployToken(ctx context.Context, projectId, deployTokenId int) (err error) - CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *models.TokenGroupDeploy, err error) + CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *token.TokenGroupDeploy, err error) RevokeGroupDeployToken(ctx context.Context, groupId, deployTokenId int) (err error) } diff --git a/internal/model/config/defaults.go b/internal/model/config/defaults.go new file mode 100644 index 0000000..e228ca0 --- /dev/null +++ b/internal/model/config/defaults.go @@ -0,0 +1,8 @@ +package config + +import "time" + +const ( + DefaultAutoRotateBeforeMinTTL = 24 * time.Hour + DefaultAutoRotateBeforeMaxTTL = 730 * time.Hour +) diff --git a/entry_config.go b/internal/model/config/entry_config.go similarity index 88% rename from entry_config.go rename to internal/model/config/entry_config.go index 2fbe057..146d4bc 100644 --- a/entry_config.go +++ b/internal/model/config/entry_config.go @@ -1,7 +1,6 @@ -package gitlab +package config import ( - "context" "crypto/sha1" "fmt" "strconv" @@ -10,13 +9,15 @@ import ( "github.com/hashicorp/go-multierror" "github.com/hashicorp/vault/sdk/framework" - "github.com/hashicorp/vault/sdk/logical" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) +var _ model.Named = (*EntryConfig)(nil) + type EntryConfig struct { TokenId int `json:"token_id" yaml:"token_id" mapstructure:"token_id"` BaseURL string `json:"base_url" structs:"base_url" mapstructure:"base_url"` @@ -33,6 +34,8 @@ type EntryConfig struct { GitlabIsEnterprise bool `json:"gitlab_is_enterprise" structs:"gitlab_is_enterprise" mapstructure:"gitlab_is_enterprise"` } +func (e *EntryConfig) GetName() string { return e.Name } + func (e *EntryConfig) Merge(data *framework.FieldData) (warnings []string, changes map[string]string, err error) { var er error if data == nil { @@ -174,26 +177,3 @@ func (e *EntryConfig) LogicalResponseData(includeToken bool) (data map[string]an return data } - -func getConfig(ctx context.Context, s logical.Storage, name string) (cfg *EntryConfig, err error) { - if s == nil { - return nil, fmt.Errorf("%w: local.Storage", errs.ErrNilValue) - } - var entry *logical.StorageEntry - if entry, err = s.Get(ctx, fmt.Sprintf("%s/%s", PathConfigStorage, name)); err == nil { - if entry == nil { - return nil, nil - } - cfg = new(EntryConfig) - _ = entry.DecodeJSON(cfg) - } - return cfg, err -} - -func saveConfig(ctx context.Context, config EntryConfig, s logical.Storage) (err error) { - var storageEntry *logical.StorageEntry - if storageEntry, err = logical.StorageEntryJSON(fmt.Sprintf("%s/%s", PathConfigStorage, config.Name), config); err == nil { - err = s.Put(ctx, storageEntry) - } - return err -} diff --git a/entry_config_merge_test.go b/internal/model/config/entry_config_merge_test.go similarity index 70% rename from entry_config_merge_test.go rename to internal/model/config/entry_config_merge_test.go index 2beee73..1e6f100 100644 --- a/entry_config_merge_test.go +++ b/internal/model/config/entry_config_merge_test.go @@ -1,6 +1,4 @@ -//go:build unit - -package gitlab_test +package config_test import ( "testing" @@ -14,11 +12,13 @@ import ( gitlab "github.com/ilijamt/vault-plugin-secrets-gitlab" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" gitlab2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) func TestEntryConfigMerge(t *testing.T) { t.Run("nil data", func(t *testing.T) { - e := new(gitlab.EntryConfig) + e := new(config.EntryConfig) warnings, changes, err := e.Merge(nil) require.Empty(t, warnings) require.Empty(t, changes) @@ -26,7 +26,7 @@ func TestEntryConfigMerge(t *testing.T) { }) t.Run("unconvertible data type", func(t *testing.T) { - e := new(gitlab.EntryConfig) + e := new(config.EntryConfig) warnings, changes, err := e.Merge(&framework.FieldData{ Raw: map[string]interface{}{"token": struct{}{}}, Schema: gitlab.FieldSchemaConfig, @@ -38,8 +38,8 @@ func TestEntryConfigMerge(t *testing.T) { var tests = []struct { name string - originalConfig *gitlab.EntryConfig - expectedConfig *gitlab.EntryConfig + originalConfig *config.EntryConfig + expectedConfig *config.EntryConfig raw map[string]interface{} warnings []string changes map[string]string @@ -48,29 +48,29 @@ func TestEntryConfigMerge(t *testing.T) { }{ { name: "update type only", - originalConfig: &gitlab.EntryConfig{Type: gitlab2.TypeSelfManaged}, - expectedConfig: &gitlab.EntryConfig{Type: gitlab2.TypeSaaS}, + originalConfig: &config.EntryConfig{Type: gitlab2.TypeSelfManaged}, + expectedConfig: &config.EntryConfig{Type: gitlab2.TypeSaaS}, raw: map[string]interface{}{"type": gitlab2.TypeSaaS}, changes: map[string]string{"type": gitlab2.TypeSaaS.String()}, }, { name: "auto rotate token set to false", - originalConfig: &gitlab.EntryConfig{}, - expectedConfig: &gitlab.EntryConfig{}, + originalConfig: &config.EntryConfig{}, + expectedConfig: &config.EntryConfig{}, raw: map[string]interface{}{"auto_rotate_token": false}, changes: map[string]string{"auto_rotate_token": "false"}, }, { name: "auto rotate token set to true", - originalConfig: &gitlab.EntryConfig{AutoRotateToken: false}, - expectedConfig: &gitlab.EntryConfig{AutoRotateToken: true}, + originalConfig: &config.EntryConfig{AutoRotateToken: false}, + expectedConfig: &config.EntryConfig{AutoRotateToken: true}, raw: map[string]interface{}{"auto_rotate_token": true}, changes: map[string]string{"auto_rotate_token": "true"}, }, { name: "update type with invalid type", - originalConfig: &gitlab.EntryConfig{Type: gitlab2.TypeSelfManaged}, - expectedConfig: &gitlab.EntryConfig{Type: gitlab2.TypeSelfManaged}, + originalConfig: &config.EntryConfig{Type: gitlab2.TypeSelfManaged}, + expectedConfig: &config.EntryConfig{Type: gitlab2.TypeSelfManaged}, raw: map[string]interface{}{"type": "test"}, err: true, errMap: map[string]int{ @@ -79,54 +79,54 @@ func TestEntryConfigMerge(t *testing.T) { }, { name: "set base url to a non empty value", - originalConfig: &gitlab.EntryConfig{}, - expectedConfig: &gitlab.EntryConfig{BaseURL: "https://gitlab.com/"}, + originalConfig: &config.EntryConfig{}, + expectedConfig: &config.EntryConfig{BaseURL: "https://gitlab.com/"}, raw: map[string]interface{}{"base_url": "https://gitlab.com/"}, changes: map[string]string{"base_url": "https://gitlab.com/"}, }, { name: "set base url to an empty value should fail", - originalConfig: &gitlab.EntryConfig{BaseURL: "https://gitlab.com/"}, - expectedConfig: &gitlab.EntryConfig{BaseURL: "https://gitlab.com/"}, + originalConfig: &config.EntryConfig{BaseURL: "https://gitlab.com/"}, + expectedConfig: &config.EntryConfig{BaseURL: "https://gitlab.com/"}, raw: map[string]interface{}{"base_url": ""}, }, { name: "auto rotate before invalid value lower than min", - originalConfig: &gitlab.EntryConfig{AutoRotateBefore: gitlab.DefaultAutoRotateBeforeMinTTL + time.Hour}, - expectedConfig: &gitlab.EntryConfig{AutoRotateBefore: gitlab.DefaultAutoRotateBeforeMinTTL + time.Hour}, + originalConfig: &config.EntryConfig{AutoRotateBefore: config.DefaultAutoRotateBeforeMinTTL + time.Hour}, + expectedConfig: &config.EntryConfig{AutoRotateBefore: config.DefaultAutoRotateBeforeMinTTL + time.Hour}, raw: map[string]interface{}{"auto_rotate_before": "1h"}, err: true, errMap: map[string]int{errs.ErrInvalidValue.Error(): 1}, }, { name: "auto rotate before invalid value higher than min", - originalConfig: &gitlab.EntryConfig{AutoRotateBefore: gitlab.DefaultAutoRotateBeforeMinTTL + time.Hour}, - expectedConfig: &gitlab.EntryConfig{AutoRotateBefore: gitlab.DefaultAutoRotateBeforeMinTTL + time.Hour}, - raw: map[string]interface{}{"auto_rotate_before": (gitlab.DefaultAutoRotateBeforeMaxTTL + time.Hour).String()}, + originalConfig: &config.EntryConfig{AutoRotateBefore: config.DefaultAutoRotateBeforeMinTTL + time.Hour}, + expectedConfig: &config.EntryConfig{AutoRotateBefore: config.DefaultAutoRotateBeforeMinTTL + time.Hour}, + raw: map[string]interface{}{"auto_rotate_before": (config.DefaultAutoRotateBeforeMaxTTL + time.Hour).String()}, err: true, errMap: map[string]int{errs.ErrInvalidValue.Error(): 1}, }, { name: "auto rotate with a valid value", - originalConfig: &gitlab.EntryConfig{AutoRotateBefore: gitlab.DefaultAutoRotateBeforeMinTTL + time.Hour}, - expectedConfig: &gitlab.EntryConfig{AutoRotateBefore: gitlab.DefaultAutoRotateBeforeMinTTL + time.Hour*2}, - raw: map[string]interface{}{"auto_rotate_before": (gitlab.DefaultAutoRotateBeforeMinTTL + time.Hour*2).String()}, + originalConfig: &config.EntryConfig{AutoRotateBefore: config.DefaultAutoRotateBeforeMinTTL + time.Hour}, + expectedConfig: &config.EntryConfig{AutoRotateBefore: config.DefaultAutoRotateBeforeMinTTL + time.Hour*2}, + raw: map[string]interface{}{"auto_rotate_before": (config.DefaultAutoRotateBeforeMinTTL + time.Hour*2).String()}, err: false, changes: map[string]string{"auto_rotate_before": "26h0m0s"}, }, { name: "token a valid value", - originalConfig: &gitlab.EntryConfig{Token: "token1"}, - expectedConfig: &gitlab.EntryConfig{Token: "token"}, + originalConfig: &config.EntryConfig{Token: "token1"}, + expectedConfig: &config.EntryConfig{Token: "token"}, raw: map[string]interface{}{"token": "token"}, err: false, changes: map[string]string{"token": "*****"}, }, { name: "token an empty value", - originalConfig: &gitlab.EntryConfig{Token: "token"}, - expectedConfig: &gitlab.EntryConfig{Token: "token"}, + originalConfig: &config.EntryConfig{Token: "token"}, + expectedConfig: &config.EntryConfig{Token: "token"}, raw: map[string]interface{}{"token": ""}, err: false, }, @@ -147,7 +147,7 @@ func TestEntryConfigMerge(t *testing.T) { if test.err { assert.Error(t, err) if len(test.errMap) > 0 { - assert.EqualValues(t, countErrByName(err.(*multierror.Error)), test.errMap) + assert.EqualValues(t, utils.CountErrByName(err.(*multierror.Error)), test.errMap) } } else { assert.NoError(t, err) diff --git a/internal/model/config/entry_config_test.go b/internal/model/config/entry_config_test.go new file mode 100644 index 0000000..0234874 --- /dev/null +++ b/internal/model/config/entry_config_test.go @@ -0,0 +1,20 @@ +package config_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" +) + +func TestEntryConfig(t *testing.T) { + cfg := config.EntryConfig{ + TokenCreatedAt: time.Now(), + TokenExpiresAt: time.Now(), + } + + require.Contains(t, cfg.LogicalResponseData(true), "token") + require.NotContains(t, cfg.LogicalResponseData(false), "token") +} diff --git a/entry_config_update_form_field_data_test.go b/internal/model/config/entry_config_update_form_field_data_test.go similarity index 79% rename from entry_config_update_form_field_data_test.go rename to internal/model/config/entry_config_update_form_field_data_test.go index f617c3b..6c66080 100644 --- a/entry_config_update_form_field_data_test.go +++ b/internal/model/config/entry_config_update_form_field_data_test.go @@ -1,6 +1,4 @@ -//go:build unit - -package gitlab_test +package config_test import ( "testing" @@ -13,11 +11,13 @@ import ( gitlab "github.com/ilijamt/vault-plugin-secrets-gitlab" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" gitlab2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) func TestEntryConfigUpdateFromFieldData(t *testing.T) { t.Run("nil data", func(t *testing.T) { - e := new(gitlab.EntryConfig) + e := new(config.EntryConfig) _, err := e.UpdateFromFieldData(nil) require.ErrorIs(t, err, errs.ErrNilValue) }) @@ -25,7 +25,7 @@ func TestEntryConfigUpdateFromFieldData(t *testing.T) { var tests = []struct { name string raw map[string]interface{} - expectedConfig *gitlab.EntryConfig + expectedConfig *config.EntryConfig warnings []string err bool errMap map[string]int @@ -45,7 +45,7 @@ func TestEntryConfigUpdateFromFieldData(t *testing.T) { "base_url": "https://gitlab.com", "type": "type", }, - expectedConfig: &gitlab.EntryConfig{AutoRotateBefore: gitlab.DefaultAutoRotateBeforeMinTTL, BaseURL: "https://gitlab.com"}, + expectedConfig: &config.EntryConfig{AutoRotateBefore: config.DefaultAutoRotateBeforeMinTTL, BaseURL: "https://gitlab.com"}, warnings: []string{"auto_rotate_token not specified setting to 24h0m0s"}, err: true, errMap: map[string]int{ @@ -55,7 +55,7 @@ func TestEntryConfigUpdateFromFieldData(t *testing.T) { }, { name: "unconvertible data type", - expectedConfig: &gitlab.EntryConfig{}, + expectedConfig: &config.EntryConfig{}, raw: map[string]interface{}{ "token": struct{}{}, }, @@ -64,11 +64,11 @@ func TestEntryConfigUpdateFromFieldData(t *testing.T) { }, { name: "valid config", - expectedConfig: &gitlab.EntryConfig{ + expectedConfig: &config.EntryConfig{ Token: "token", Type: gitlab2.TypeSelfManaged, AutoRotateToken: false, - AutoRotateBefore: gitlab.DefaultAutoRotateBeforeMinTTL, + AutoRotateBefore: config.DefaultAutoRotateBeforeMinTTL, BaseURL: "https://gitlab.com", }, warnings: []string{"auto_rotate_token not specified setting to 24h0m0s"}, @@ -82,18 +82,18 @@ func TestEntryConfigUpdateFromFieldData(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - e := new(gitlab.EntryConfig) + e := new(config.EntryConfig) assert.Empty(t, e) warnings, err := e.UpdateFromFieldData(&framework.FieldData{Raw: test.raw, Schema: gitlab.FieldSchemaConfig}) assert.Equal(t, test.warnings, warnings) if test.expectedConfig == nil { - test.expectedConfig = &gitlab.EntryConfig{AutoRotateBefore: gitlab.DefaultAutoRotateBeforeMinTTL} + test.expectedConfig = &config.EntryConfig{AutoRotateBefore: config.DefaultAutoRotateBeforeMinTTL} } assert.EqualValues(t, test.expectedConfig, e) if test.err { assert.Error(t, err) if len(test.errMap) > 0 { - assert.Equal(t, countErrByName(err.(*multierror.Error)), test.errMap) + assert.Equal(t, utils.CountErrByName(err.(*multierror.Error)), test.errMap) } } else { assert.NoError(t, err) diff --git a/internal/model/model.go b/internal/model/model.go new file mode 100644 index 0000000..5825d77 --- /dev/null +++ b/internal/model/model.go @@ -0,0 +1,23 @@ +package model + +type Named interface { + // GetName returns the model's name as a string + GetName() string +} + +type IsNil interface { + // IsNil returns a boolean indicating whether the instance is considered nil or invalid + IsNil() bool +} + +type Event interface{} + +type LogicalResponseData interface { + // LogicalResponseData returns a map containing relevant data that can be used in template operations or logical evaluations + LogicalResponseData() map[string]any +} + +type LogicalResponseDataWithOptions[T any] interface { + // LogicalResponseData returns a map containing relevant data that can be used in template operations or logical evaluations + LogicalResponseData(opts T) map[string]any +} diff --git a/internal/model/ops.go b/internal/model/ops.go new file mode 100644 index 0000000..69e4e24 --- /dev/null +++ b/internal/model/ops.go @@ -0,0 +1,66 @@ +package model + +import ( + "context" + "errors" + "fmt" + + "github.com/hashicorp/vault/sdk/logical" + + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" +) + +// Delete removes the storage entry at the specified fullPath. +func Delete(ctx context.Context, s logical.Storage, fullPath string) (err error) { + if s == nil { + return fmt.Errorf("%w: local.Storage", errs.ErrNilValue) + } + return s.Delete(ctx, fullPath) +} + +// Save marshals and stores 'data' at the given rootPath in storage 's'. +func Save(ctx context.Context, s logical.Storage, rootPath string, data Named) (err error) { + if s == nil { + err = errors.Join(err, fmt.Errorf("local.Storage: %w", errs.ErrNilValue)) + } + + if data == nil { + err = errors.Join(err, fmt.Errorf("%w: model", errs.ErrNilValue)) + } + + if err != nil { + return err + } + + var entry *logical.StorageEntry + if entry, err = logical.StorageEntryJSON(fmt.Sprintf("%s/%s", rootPath, data.GetName()), data); err == nil { + err = s.Put(ctx, entry) + } + return err +} + +// Get retrieves and decodes an entry at fullPath into a new T. +// Returns (nil, nil) if the entry is not found. +func Get[T any](ctx context.Context, s logical.Storage, fullPath string) (data *T, err error) { + if s == nil { + return nil, fmt.Errorf("%w: local.Storage", errs.ErrNilValue) + } + var entry *logical.StorageEntry + if entry, err = s.Get(ctx, fullPath); err == nil { + if entry == nil { + return nil, nil + } + data = new(T) + err = entry.DecodeJSON(data) + } + + return data, err +} + +// List returns the list of keys at fullPath in storage. +func List(ctx context.Context, s logical.Storage, fullPath string) (entries []string, err error) { + if s == nil { + return entries, fmt.Errorf("%w: local.Storage", errs.ErrNilValue) + } + return s.List(ctx, fullPath) +} diff --git a/internal/model/ops_test.go b/internal/model/ops_test.go new file mode 100644 index 0000000..1e5323c --- /dev/null +++ b/internal/model/ops_test.go @@ -0,0 +1,61 @@ +package model_test + +import ( + "testing" + + "github.com/hashicorp/vault/sdk/logical" + "github.com/stretchr/testify/require" + + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model" +) + +type emptyModel struct { + Name string `json:"name"` +} + +func (d emptyModel) GetName() string { + return d.Name +} + +func TestModel(t *testing.T) { + t.Run("nil storage", func(t *testing.T) { + var err error + + require.ErrorIs(t, model.Delete(t.Context(), nil, "path"), errs.ErrNilValue) + require.ErrorIs(t, model.Save(t.Context(), nil, "path", nil), errs.ErrNilValue) + + _, err = model.List(t.Context(), nil, "path") + require.ErrorIs(t, err, errs.ErrNilValue) + + _, err = model.Get[any](t.Context(), nil, "test") + require.ErrorIs(t, err, errs.ErrNilValue) + }) + + t.Run("ops", func(t *testing.T) { + var path = "path/test" + storage := &logical.InmemStorage{} + + data, err := model.Get[emptyModel](t.Context(), storage, path) + require.NoError(t, err) + require.Nil(t, data) + + data = &emptyModel{Name: "test"} + + require.NoError(t, model.Save(t.Context(), storage, "path", data)) + + data, err = model.Get[emptyModel](t.Context(), storage, path) + require.NoError(t, err) + require.NotNil(t, data) + require.Equal(t, "test", data.GetName()) + + var entries []string + entries, err = model.List(t.Context(), storage, "path/") + require.Len(t, entries, 1) + + require.NoError(t, model.Delete(t.Context(), storage, path)) + + entries, err = model.List(t.Context(), storage, "path/") + require.Len(t, entries, 0) + }) +} diff --git a/entry_role.go b/internal/model/role/role.go similarity index 71% rename from entry_role.go rename to internal/model/role/role.go index d89bba6..633758f 100644 --- a/entry_role.go +++ b/internal/model/role/role.go @@ -1,17 +1,18 @@ -package gitlab +package role import ( - "context" - "fmt" "strings" "time" - "github.com/hashicorp/vault/sdk/logical" - + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" ) -type EntryRole struct { +var _ model.Named = (*Role)(nil) +var _ model.IsNil = (*Role)(nil) +var _ model.LogicalResponseData = (*Role)(nil) + +type Role struct { RoleName string `json:"role_name" structs:"role_name" mapstructure:"role_name"` TTL time.Duration `json:"ttl" structs:"ttl" mapstructure:"ttl"` Path string `json:"path" structs:"path" mapstructure:"path"` @@ -23,15 +24,13 @@ type EntryRole struct { ConfigName string `json:"config_name" structs:"config_name" mapstructure:"config_name"` } -func (e EntryRole) IsNil() bool { - return false -} +func (e Role) IsNil() bool { return false } -func (e EntryRole) GetName() string { +func (e Role) GetName() string { return e.Name } -func (e EntryRole) LogicalResponseData() map[string]any { +func (e Role) LogicalResponseData() map[string]any { return map[string]any{ "role_name": e.RoleName, "path": e.Path, @@ -44,15 +43,3 @@ func (e EntryRole) LogicalResponseData() map[string]any { "config_name": e.ConfigName, } } - -func getRole(ctx context.Context, name string, s logical.Storage) (role *EntryRole, err error) { - var entry *logical.StorageEntry - if entry, err = s.Get(ctx, fmt.Sprintf("%s/%s", PathRoleStorage, name)); err == nil { - if entry == nil { - return nil, nil - } - role = new(EntryRole) - _ = entry.DecodeJSON(role) - } - return role, err -} diff --git a/internal/model/role/role_test.go b/internal/model/role/role_test.go new file mode 100644 index 0000000..4138179 --- /dev/null +++ b/internal/model/role/role_test.go @@ -0,0 +1,16 @@ +package role_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/role" +) + +func TestRule(t *testing.T) { + r := role.Role{Name: "Name"} + require.False(t, r.IsNil()) + require.EqualValues(t, "Name", r.GetName()) + require.NotEmpty(t, r.LogicalResponseData()) +} diff --git a/internal/models/token.go b/internal/model/token/token.go similarity index 99% rename from internal/models/token.go rename to internal/model/token/token.go index 705b96c..3806433 100644 --- a/internal/models/token.go +++ b/internal/model/token/token.go @@ -1,4 +1,4 @@ -package models +package token import ( "crypto/sha1" diff --git a/internal/models/token_config.go b/internal/model/token/token_config.go similarity index 97% rename from internal/models/token_config.go rename to internal/model/token/token_config.go index 2d22c45..4c395ab 100644 --- a/internal/models/token_config.go +++ b/internal/model/token/token_config.go @@ -1,4 +1,4 @@ -package models +package token import ( "maps" diff --git a/internal/models/token_config_test.go b/internal/model/token/token_config_test.go similarity index 75% rename from internal/models/token_config_test.go rename to internal/model/token/token_config_test.go index 88f82e4..a9e7f32 100644 --- a/internal/models/token_config_test.go +++ b/internal/model/token/token_config_test.go @@ -1,15 +1,15 @@ -package models_test +package token_test import ( "testing" "github.com/stretchr/testify/assert" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" ) func TestTokenConfig(t *testing.T) { - data := models.TokenConfig{UserID: 1} + data := token.TokenConfig{UserID: 1} assert.Contains(t, data.Data(), "user_id") assert.Contains(t, data.Event(nil), "user_id") assert.Contains(t, data.Internal(), "user_id") diff --git a/internal/models/token_group.go b/internal/model/token/token_group.go similarity index 92% rename from internal/models/token_group.go rename to internal/model/token/token_group.go index 85a3097..dfd057b 100644 --- a/internal/models/token_group.go +++ b/internal/model/token/token_group.go @@ -1,4 +1,4 @@ -package models +package token import "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" diff --git a/internal/models/token_group_deploy.go b/internal/model/token/token_group_deploy.go similarity index 97% rename from internal/models/token_group_deploy.go rename to internal/model/token/token_group_deploy.go index 773c55f..81ac8d9 100644 --- a/internal/models/token_group_deploy.go +++ b/internal/model/token/token_group_deploy.go @@ -1,4 +1,4 @@ -package models +package token import ( "maps" diff --git a/internal/models/token_group_deploy_test.go b/internal/model/token/token_group_deploy_test.go similarity index 75% rename from internal/models/token_group_deploy_test.go rename to internal/model/token/token_group_deploy_test.go index 67e5153..c02ffbb 100644 --- a/internal/models/token_group_deploy_test.go +++ b/internal/model/token/token_group_deploy_test.go @@ -1,15 +1,15 @@ -package models_test +package token_test import ( "testing" "github.com/stretchr/testify/assert" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" ) func TestTokenGroupDeploy(t *testing.T) { - data := models.TokenGroupDeploy{Username: "username"} + data := token.TokenGroupDeploy{Username: "username"} assert.Contains(t, data.Data(), "username") assert.Contains(t, data.Event(nil), "username") assert.Contains(t, data.Internal(), "username") diff --git a/internal/models/token_group_service_account.go b/internal/model/token/token_group_service_account.go similarity index 98% rename from internal/models/token_group_service_account.go rename to internal/model/token/token_group_service_account.go index 9dfa886..dd52064 100644 --- a/internal/models/token_group_service_account.go +++ b/internal/model/token/token_group_service_account.go @@ -1,4 +1,4 @@ -package models +package token import ( "maps" diff --git a/internal/models/token_group_service_account_test.go b/internal/model/token/token_group_service_account_test.go similarity index 74% rename from internal/models/token_group_service_account_test.go rename to internal/model/token/token_group_service_account_test.go index f83f563..d522fd5 100644 --- a/internal/models/token_group_service_account_test.go +++ b/internal/model/token/token_group_service_account_test.go @@ -1,15 +1,15 @@ -package models_test +package token_test import ( "testing" "github.com/stretchr/testify/assert" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" ) func TestTokenGroupServiceAccount(t *testing.T) { - data := models.TokenGroupServiceAccount{UserID: 1} + data := token.TokenGroupServiceAccount{UserID: 1} assert.Contains(t, data.Data(), "user_id") assert.Contains(t, data.Event(nil), "user_id") assert.Contains(t, data.Internal(), "user_id") diff --git a/internal/models/token_personal.go b/internal/model/token/token_personal.go similarity index 97% rename from internal/models/token_personal.go rename to internal/model/token/token_personal.go index 30608fa..a30eec3 100644 --- a/internal/models/token_personal.go +++ b/internal/model/token/token_personal.go @@ -1,4 +1,4 @@ -package models +package token import ( "maps" diff --git a/internal/models/token_personal_test.go b/internal/model/token/token_personal_test.go similarity index 75% rename from internal/models/token_personal_test.go rename to internal/model/token/token_personal_test.go index a7a306a..cb92aa5 100644 --- a/internal/models/token_personal_test.go +++ b/internal/model/token/token_personal_test.go @@ -1,15 +1,15 @@ -package models_test +package token_test import ( "testing" "github.com/stretchr/testify/assert" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" ) func TestTokenPersonal(t *testing.T) { - data := models.TokenPersonal{UserID: 1} + data := token.TokenPersonal{UserID: 1} assert.Contains(t, data.Data(), "user_id") assert.Contains(t, data.Event(nil), "user_id") assert.Contains(t, data.Internal(), "user_id") diff --git a/internal/models/token_pipeline_project_trigger.go b/internal/model/token/token_pipeline_project_trigger.go similarity index 92% rename from internal/models/token_pipeline_project_trigger.go rename to internal/model/token/token_pipeline_project_trigger.go index 62fc427..ac39d9b 100644 --- a/internal/models/token_pipeline_project_trigger.go +++ b/internal/model/token/token_pipeline_project_trigger.go @@ -1,4 +1,4 @@ -package models +package token import "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" diff --git a/internal/models/token_project.go b/internal/model/token/token_project.go similarity index 92% rename from internal/models/token_project.go rename to internal/model/token/token_project.go index 04c451e..580e589 100644 --- a/internal/models/token_project.go +++ b/internal/model/token/token_project.go @@ -1,4 +1,4 @@ -package models +package token import "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" diff --git a/internal/models/token_project_deploy.go b/internal/model/token/token_project_deploy.go similarity index 97% rename from internal/models/token_project_deploy.go rename to internal/model/token/token_project_deploy.go index c5be3ea..cc61db8 100644 --- a/internal/models/token_project_deploy.go +++ b/internal/model/token/token_project_deploy.go @@ -1,4 +1,4 @@ -package models +package token import ( "maps" diff --git a/internal/models/token_project_deploy_test.go b/internal/model/token/token_project_deploy_test.go similarity index 75% rename from internal/models/token_project_deploy_test.go rename to internal/model/token/token_project_deploy_test.go index 191388d..260dcf1 100644 --- a/internal/models/token_project_deploy_test.go +++ b/internal/model/token/token_project_deploy_test.go @@ -1,15 +1,15 @@ -package models_test +package token_test import ( "testing" "github.com/stretchr/testify/assert" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" ) func TestTokenProjectDeploy(t *testing.T) { - data := models.TokenProjectDeploy{Username: "username"} + data := token.TokenProjectDeploy{Username: "username"} assert.Contains(t, data.Data(), "username") assert.Contains(t, data.Event(nil), "username") assert.Contains(t, data.Internal(), "username") diff --git a/internal/models/token_test.go b/internal/model/token/token_test.go similarity index 88% rename from internal/models/token_test.go rename to internal/model/token/token_test.go index d75c9eb..efb53b0 100644 --- a/internal/models/token_test.go +++ b/internal/model/token/token_test.go @@ -1,4 +1,4 @@ -package models_test +package token_test import ( "testing" @@ -7,26 +7,26 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + token2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" ) func TestToken(t *testing.T) { t.Run("expires is not set so we get a 0 ttl", func(t *testing.T) { - data := models.Token{} + data := token2.Token{} require.EqualValues(t, 0, data.TTL()) }) t.Run("ttl has a value if both created and expires are set", func(t *testing.T) { cat := time.Date(2025, 1, 1, 1, 0, 0, 0, time.UTC) - data := models.Token{CreatedAt: &cat} + data := token2.Token{CreatedAt: &cat} eat := time.Date(2025, 1, 1, 2, 0, 0, 0, time.UTC) data.SetExpiresAt(&eat) require.EqualValues(t, time.Hour, data.TTL()) }) t.Run("setters", func(t *testing.T) { - data := models.Token{} + data := token2.Token{} data.SetRoleName("role-name") data.SetConfigName("config-name") data.SetGitlabRevokesToken(true) @@ -39,7 +39,7 @@ func TestToken(t *testing.T) { } func TestTokenWithScopes(t *testing.T) { - data := models.TokenWithScopes{Scopes: []string{"scope1", "scope2"}} + data := token2.TokenWithScopes{Scopes: []string{"scope1", "scope2"}} assert.Contains(t, data.Data(), "scopes") assert.Contains(t, data.Event(nil), "scopes") assert.Contains(t, data.Internal(), "scopes") @@ -49,7 +49,7 @@ func TestTokenWithScopes(t *testing.T) { } func TestTokenWithScopesAndAccessLevel(t *testing.T) { - data := models.TokenWithScopesAndAccessLevel{ + data := token2.TokenWithScopesAndAccessLevel{ Scopes: []string{"scope1", "scope2"}, AccessLevel: token.AccessLevelNoPermissions, } diff --git a/internal/models/token_user_service_account.go b/internal/model/token/token_user_service_account.go similarity index 93% rename from internal/models/token_user_service_account.go rename to internal/model/token/token_user_service_account.go index 5a28df1..4813941 100644 --- a/internal/models/token_user_service_account.go +++ b/internal/model/token/token_user_service_account.go @@ -1,4 +1,4 @@ -package models +package token import "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" diff --git a/internal/utils/count_err_by_name.go b/internal/utils/count_err_by_name.go new file mode 100644 index 0000000..f66f142 --- /dev/null +++ b/internal/utils/count_err_by_name.go @@ -0,0 +1,32 @@ +package utils + +import ( + "errors" + + "github.com/hashicorp/go-multierror" +) + +func CountErrByName(err *multierror.Error) map[string]int { + data := make(map[string]int) + + if err == nil || err.Errors == nil { + return data + } + + for _, e := range err.Errors { + if e == nil { + continue + } + + var name string + if unwrapped := errors.Unwrap(e); unwrapped != nil { + name = unwrapped.Error() + } else { + name = e.Error() + } + + data[name]++ + } + + return data +} diff --git a/internal/utils/count_err_by_name_test.go b/internal/utils/count_err_by_name_test.go new file mode 100644 index 0000000..a4e81e2 --- /dev/null +++ b/internal/utils/count_err_by_name_test.go @@ -0,0 +1,79 @@ +package utils_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/go-multierror" + "github.com/stretchr/testify/assert" + + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" +) + +func TestCountErrByName(t *testing.T) { + // Test with nil multierror + var nilErr *multierror.Error + result := utils.CountErrByName(nilErr) + assert.Empty(t, result) + + // Test with multierror having nil Errors slice + multiErr := &multierror.Error{Errors: nil} + result = utils.CountErrByName(multiErr) + assert.Empty(t, result) + + // Test with empty multierror + emptyErr := &multierror.Error{Errors: []error{}} + result = utils.CountErrByName(emptyErr) + assert.Empty(t, result) + + // Test with nil error in slice + multiErr = &multierror.Error{Errors: []error{nil}} + result = utils.CountErrByName(multiErr) + assert.Empty(t, result) + + // Test with single error + err1 := fmt.Errorf("error1") + multiErr = &multierror.Error{Errors: []error{err1}} + result = utils.CountErrByName(multiErr) + expected := map[string]int{"error1": 1} + assert.Equal(t, expected, result) + + // Test with wrapped error + wrappedErr := fmt.Errorf("wrapped: %w", fmt.Errorf("original")) + multiErr = &multierror.Error{Errors: []error{wrappedErr}} + result = utils.CountErrByName(multiErr) + expected = map[string]int{"original": 1} + assert.Equal(t, expected, result) + + // Test with non-wrapped error (Unwrap returns nil) + nonWrappedErr := fmt.Errorf("non-wrapped") + multiErr = &multierror.Error{Errors: []error{nonWrappedErr}} + result = utils.CountErrByName(multiErr) + expected = map[string]int{"non-wrapped": 1} + assert.Equal(t, expected, result) + + // Test with multiple different errors + err2 := fmt.Errorf("error2") + multiErr = &multierror.Error{Errors: []error{err1, err2}} + result = utils.CountErrByName(multiErr) + expected = map[string]int{"error1": 1, "error2": 1} + assert.Equal(t, expected, result) + + // Test with duplicate errors + multiErr = &multierror.Error{Errors: []error{err1, err1, err2}} + result = utils.CountErrByName(multiErr) + expected = map[string]int{"error1": 2, "error2": 1} + assert.Equal(t, expected, result) + + // Test with mix of nil and valid errors + multiErr = &multierror.Error{Errors: []error{nil, err1, nil, err2, err1}} + result = utils.CountErrByName(multiErr) + expected = map[string]int{"error1": 2, "error2": 1} + assert.Equal(t, expected, result) + + // Test with wrapped and non-wrapped errors mixed + multiErr = &multierror.Error{Errors: []error{wrappedErr, nonWrappedErr}} + result = utils.CountErrByName(multiErr) + expected = map[string]int{"original": 1, "non-wrapped": 1} + assert.Equal(t, expected, result) +} diff --git a/path_config.go b/path_config.go index ba359bd..66b2fd6 100644 --- a/path_config.go +++ b/path_config.go @@ -15,7 +15,8 @@ import ( "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/event" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + config2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) @@ -109,7 +110,7 @@ func (b *Backend) pathConfigRead(ctx context.Context, req *logical.Request, data defer b.lockClientMutex.RUnlock() var name = data.Get("config_name").(string) - var config *EntryConfig + var config *config2.EntryConfig if config, err = getConfig(ctx, req.Storage, name); err == nil { if config == nil { return logical.ErrorResponse(errs.ErrBackendNotConfigured.Error()), nil @@ -125,7 +126,7 @@ func (b *Backend) pathConfigPatch(ctx context.Context, req *logical.Request, dat var name = data.Get("config_name").(string) var warnings []string var changes map[string]string - var config *EntryConfig + var config *config2.EntryConfig config, err = getConfig(ctx, req.Storage, name) if err != nil { return nil, err @@ -147,7 +148,7 @@ func (b *Backend) pathConfigPatch(ctx context.Context, req *logical.Request, dat b.lockClientMutex.Lock() defer b.lockClientMutex.Unlock() - if err = saveConfig(ctx, *config, req.Storage); err == nil { + if err = saveConfig(ctx, config, req.Storage); err == nil { lrd := config.LogicalResponseData(b.flags.ShowConfigToken) _ = event.Event(ctx, b.Backend, operationPrefixGitlabAccessTokens, "config-patch", changes) b.SetClient(nil, name) @@ -158,7 +159,7 @@ func (b *Backend) pathConfigPatch(ctx context.Context, req *logical.Request, dat return lResp, err } -func (b *Backend) updateConfigClientInfo(ctx context.Context, config *EntryConfig) (et *models.TokenConfig, err error) { +func (b *Backend) updateConfigClientInfo(ctx context.Context, config *config2.EntryConfig) (et *token.TokenConfig, err error) { var httpClient *http.Client var client Client httpClient, _ = utils.HttpClientFromContext(ctx) @@ -192,7 +193,7 @@ func (b *Backend) updateConfigClientInfo(ctx context.Context, config *EntryConfi func (b *Backend) pathConfigWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { var name = data.Get("config_name").(string) - var config = new(EntryConfig) + var config = new(config2.EntryConfig) var warnings, err = config.UpdateFromFieldData(data) if err != nil { return nil, err @@ -207,7 +208,7 @@ func (b *Backend) pathConfigWrite(ctx context.Context, req *logical.Request, dat defer b.lockClientMutex.Unlock() var lResp *logical.Response - if err = saveConfig(ctx, *config, req.Storage); err == nil { + if err = saveConfig(ctx, config, req.Storage); err == nil { _ = event.Event(ctx, b.Backend, operationPrefixGitlabAccessTokens, "config-write", map[string]string{ "path": fmt.Sprintf("%s/%s", PathConfigStorage, name), "auto_rotate_token": strconv.FormatBool(config.AutoRotateToken), diff --git a/path_config_rotate.go b/path_config_rotate.go index a810c50..3042e68 100644 --- a/path_config_rotate.go +++ b/path_config_rotate.go @@ -13,7 +13,8 @@ import ( "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/event" - "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/models" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/token" ) const pathConfigRotateHelpSynopsis = `Rotate the gitlab token for this configuration.` @@ -44,7 +45,7 @@ func pathConfigTokenRotate(b *Backend) *framework.Path { } } -func (b *Backend) checkAndRotateConfigToken(ctx context.Context, request *logical.Request, config *EntryConfig) error { +func (b *Backend) checkAndRotateConfigToken(ctx context.Context, request *logical.Request, config *config.EntryConfig) error { var err error b.Logger().Debug("Running check and rotate config token") if time.Until(config.TokenExpiresAt) <= config.AutoRotateBefore { @@ -61,7 +62,7 @@ func (b *Backend) checkAndRotateConfigToken(ctx context.Context, request *logica func (b *Backend) pathConfigTokenRotate(ctx context.Context, request *logical.Request, data *framework.FieldData) (lResp *logical.Response, err error) { var name = data.Get("config_name").(string) b.Logger().Debug("Running pathConfigTokenRotate") - var config *EntryConfig + var config *config.EntryConfig var client Client b.lockClientMutex.RLock() @@ -81,7 +82,7 @@ func (b *Backend) pathConfigTokenRotate(ctx context.Context, request *logical.Re return nil, err } - var entryToken *models.TokenConfig + var entryToken *token.TokenConfig entryToken, _, err = client.RotateCurrentToken(ctx) if err != nil { b.Logger().Error("Failed to rotate main token", "err", err) @@ -99,7 +100,7 @@ func (b *Backend) pathConfigTokenRotate(ctx context.Context, request *logical.Re } b.lockClientMutex.Lock() defer b.lockClientMutex.Unlock() - err = saveConfig(ctx, *config, request.Storage) + err = saveConfig(ctx, config, request.Storage) if err != nil { b.Logger().Error("failed to store configuration for revocation", "err", err) return nil, err diff --git a/path_config_test.go b/path_config_test.go index 266138d..3a88b90 100644 --- a/path_config_test.go +++ b/path_config_test.go @@ -197,7 +197,7 @@ func TestPathConfig(t *testing.T) { require.Error(t, err) require.Nil(t, resp) - var errorMap = countErrByName(err.(*multierror.Error)) + var errorMap = utils.CountErrByName(err.(*multierror.Error)) assert.EqualValues(t, 3, errorMap[errs.ErrFieldRequired.Error()]) require.Len(t, errorMap, 1) }) diff --git a/path_config_token_autorotate_test.go b/path_config_token_autorotate_test.go index 836b226..8c8abbd 100644 --- a/path_config_token_autorotate_test.go +++ b/path_config_token_autorotate_test.go @@ -14,6 +14,7 @@ import ( gitlab "github.com/ilijamt/vault-plugin-secrets-gitlab" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" gitlab2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" ) func TestPathConfig_AutoRotate(t *testing.T) { @@ -64,7 +65,7 @@ func TestPathConfig_AutoRotate(t *testing.T) { Data: map[string]any{ "token": getGitlabToken("admin_user_root").Token, "base_url": url, - "auto_rotate_before": (gitlab.DefaultAutoRotateBeforeMaxTTL + time.Hour).String(), + "auto_rotate_before": (config.DefaultAutoRotateBeforeMaxTTL + time.Hour).String(), "type": gitlab2.TypeSelfManaged.String(), }, }) @@ -101,7 +102,7 @@ func TestPathConfig_AutoRotate(t *testing.T) { Data: map[string]any{ "token": getGitlabToken("admin_user_root").Token, "base_url": url, - "auto_rotate_before": (gitlab.DefaultAutoRotateBeforeMinTTL - time.Hour).String(), + "auto_rotate_before": (config.DefaultAutoRotateBeforeMinTTL - time.Hour).String(), "type": gitlab2.TypeSelfManaged.String(), }, }) diff --git a/path_role.go b/path_role.go index e0a651d..4e6ba7e 100644 --- a/path_role.go +++ b/path_role.go @@ -17,6 +17,8 @@ import ( "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/event" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" + config2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/config" + role2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/role" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) @@ -201,7 +203,7 @@ func (b *Backend) pathRolesRead(ctx context.Context, req *logical.Request, data func (b *Backend) pathRolesWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { var roleName = data.Get("role_name").(string) - var config *EntryConfig + var config *config2.EntryConfig var err error var warnings []string var tokenType token.Type @@ -222,7 +224,7 @@ func (b *Backend) pathRolesWrite(ctx context.Context, req *logical.Request, data tokenType, _ = token.ParseType(data.Get("token_type").(string)) accessLevel, _ = token.AccessLevelParse(data.Get("access_level").(string)) - var role = EntryRole{ + var role = role2.Role{ RoleName: roleName, TTL: time.Duration(data.Get("ttl").(int)) * time.Second, Path: data.Get("path").(string), diff --git a/path_role_deploy_tokens_test.go b/path_role_deploy_tokens_test.go index e7bd85c..e092c21 100644 --- a/path_role_deploy_tokens_test.go +++ b/path_role_deploy_tokens_test.go @@ -18,6 +18,7 @@ import ( "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" gitlab2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) func TestPathRolesDeployTokens(t *testing.T) { @@ -87,7 +88,7 @@ func TestPathRolesDeployTokens(t *testing.T) { }) require.Error(t, err) require.NotNil(t, resp) - var errorMap = countErrByName(err.(*multierror.Error)) + var errorMap = utils.CountErrByName(err.(*multierror.Error)) assert.EqualValues(t, 2, errorMap[errs.ErrFieldInvalidValue.Error()]) }) }) diff --git a/path_role_pipeline_project_trigger_token_test.go b/path_role_pipeline_project_trigger_token_test.go index 5b05ec4..151fad3 100644 --- a/path_role_pipeline_project_trigger_token_test.go +++ b/path_role_pipeline_project_trigger_token_test.go @@ -18,6 +18,7 @@ import ( "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" gitlab2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) func TestPathRolesPipelineProjectTrigger(t *testing.T) { @@ -45,7 +46,7 @@ func TestPathRolesPipelineProjectTrigger(t *testing.T) { }) require.Error(t, err) require.NotNil(t, resp) - var errorMap = countErrByName(err.(*multierror.Error)) + var errorMap = utils.CountErrByName(err.(*multierror.Error)) assert.EqualValues(t, 2, errorMap[errs.ErrFieldInvalidValue.Error()]) }) diff --git a/path_role_test.go b/path_role_test.go index 7eba239..5423fb2 100644 --- a/path_role_test.go +++ b/path_role_test.go @@ -19,6 +19,7 @@ import ( "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" gitlab2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/gitlab" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" + "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) func TestPathRolesList(t *testing.T) { @@ -221,7 +222,7 @@ func TestPathRoles(t *testing.T) { require.Error(t, err) require.NotNil(t, resp) require.Error(t, resp.Error()) - var errorMap = countErrByName(err.(*multierror.Error)) + var errorMap = utils.CountErrByName(err.(*multierror.Error)) assert.EqualValues(t, 4, errorMap[errs.ErrFieldRequired.Error()]) assert.EqualValues(t, 2, errorMap[errs.ErrFieldInvalidValue.Error()]) }) @@ -289,7 +290,7 @@ func TestPathRoles(t *testing.T) { }) require.Error(t, err) require.NotNil(t, resp) - var errorMap = countErrByName(err.(*multierror.Error)) + var errorMap = utils.CountErrByName(err.(*multierror.Error)) assert.EqualValues(t, 1, errorMap[errs.ErrFieldInvalidValue.Error()]) }) }) @@ -333,7 +334,7 @@ func TestPathRoles(t *testing.T) { }) require.Error(t, err) require.NotNil(t, resp) - var errorMap = countErrByName(err.(*multierror.Error)) + var errorMap = utils.CountErrByName(err.(*multierror.Error)) assert.EqualValues(t, 1, errorMap[errs.ErrFieldInvalidValue.Error()]) }) }) @@ -377,7 +378,7 @@ func TestPathRoles(t *testing.T) { }) require.Error(t, err) require.NotNil(t, resp) - var errorMap = countErrByName(err.(*multierror.Error)) + var errorMap = utils.CountErrByName(err.(*multierror.Error)) assert.EqualValues(t, 1, errorMap[errs.ErrFieldInvalidValue.Error()]) }) }) diff --git a/path_token_role.go b/path_token_role.go index 0a357f7..879fd84 100644 --- a/path_token_role.go +++ b/path_token_role.go @@ -14,6 +14,7 @@ import ( "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/errs" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/event" + role2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/model/role" token2 "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/token" "github.com/ilijamt/vault-plugin-secrets-gitlab/internal/utils" ) @@ -42,7 +43,7 @@ var ( func (b *Backend) pathTokenRoleCreate(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { var resp *logical.Response var err error - var role *EntryRole + var role *role2.Role var roleName = data.Get("role_name").(string) lock := locksutil.LockForKey(b.roleLocks, roleName)