feat: [AH-1261]: fix auth issue in gitness (#3732)

* feat: [AH-1261]: fix auth issue in gitness
This commit is contained in:
Tudor Macari 2025-04-29 20:05:51 +00:00 committed by Harness
parent 6aa9e3cfbc
commit 57f613cac1
15 changed files with 128 additions and 89 deletions

View File

@ -527,7 +527,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
} }
registryHelper := rpm.LocalRegistryHelperProvider(fileManager, artifactRepository) registryHelper := rpm.LocalRegistryHelperProvider(fileManager, artifactRepository)
indexService := index.ProvideService(registryHelper) indexService := index.ProvideService(registryHelper)
apiHandler := router.APIHandlerProvider(registryRepository, upstreamProxyConfigRepository, fileManager, tagRepository, manifestRepository, cleanupPolicyRepository, imageRepository, storageDriver, spaceFinder, transactor, authenticator, provider, authorizer, auditService, artifactRepository, webhooksRepository, webhooksExecutionRepository, service2, spacePathStore, reporter10, downloadStatRepository, indexService) apiHandler := router.APIHandlerProvider(registryRepository, upstreamProxyConfigRepository, fileManager, tagRepository, manifestRepository, cleanupPolicyRepository, imageRepository, storageDriver, spaceFinder, transactor, authenticator, provider, authorizer, auditService, artifactRepository, webhooksRepository, webhooksExecutionRepository, service2, spacePathStore, reporter10, downloadStatRepository, indexService, config)
mavenDBStore := maven.DBStoreProvider(registryRepository, imageRepository, artifactRepository, spaceStore, bandwidthStatRepository, downloadStatRepository, nodesRepository, upstreamProxyConfigRepository) mavenDBStore := maven.DBStoreProvider(registryRepository, imageRepository, artifactRepository, spaceStore, bandwidthStatRepository, downloadStatRepository, nodesRepository, upstreamProxyConfigRepository)
mavenLocalRegistry := maven.LocalRegistryProvider(mavenDBStore, transactor, fileManager) mavenLocalRegistry := maven.LocalRegistryProvider(mavenDBStore, transactor, fileManager)
mavenController := maven.ProvideProxyController(mavenLocalRegistry, secretService, spaceFinder) mavenController := maven.ProvideProxyController(mavenLocalRegistry, secretService, spaceFinder)

View File

@ -37,6 +37,7 @@ func GetArtifactMetadata(
artifacts []types.ArtifactMetadata, artifacts []types.ArtifactMetadata,
rootIdentifier string, rootIdentifier string,
urlProvider url.Provider, urlProvider url.Provider,
setupDetailsAuthHeaderPrefix string,
) []artifactapi.ArtifactMetadata { ) []artifactapi.ArtifactMetadata {
artifactMetadataList := make([]artifactapi.ArtifactMetadata, 0, len(artifacts)) artifactMetadataList := make([]artifactapi.ArtifactMetadata, 0, len(artifacts))
for _, artifact := range artifacts { for _, artifact := range artifacts {
@ -44,7 +45,7 @@ func GetArtifactMetadata(
if artifact.PackageType == artifactapi.PackageTypeGENERIC { if artifact.PackageType == artifactapi.PackageTypeGENERIC {
registryURL = urlProvider.RegistryURL(ctx, rootIdentifier, "generic", artifact.RepoName) registryURL = urlProvider.RegistryURL(ctx, rootIdentifier, "generic", artifact.RepoName)
} }
artifactMetadata := mapToArtifactMetadata(artifact, registryURL) artifactMetadata := mapToArtifactMetadata(artifact, registryURL, setupDetailsAuthHeaderPrefix)
artifactMetadataList = append(artifactMetadataList, *artifactMetadata) artifactMetadataList = append(artifactMetadataList, *artifactMetadata)
} }
return artifactMetadataList return artifactMetadataList
@ -83,11 +84,12 @@ func GetMavenArtifactDetail(
func mapToArtifactMetadata( func mapToArtifactMetadata(
artifact types.ArtifactMetadata, artifact types.ArtifactMetadata,
registryURL string, registryURL string,
setupDetailsAuthHeaderPrefix string,
) *artifactapi.ArtifactMetadata { ) *artifactapi.ArtifactMetadata {
lastModified := GetTimeInMs(artifact.ModifiedAt) lastModified := GetTimeInMs(artifact.ModifiedAt)
packageType := artifact.PackageType packageType := artifact.PackageType
pullCommand := GetPullCommand(artifact.Name, artifact.Version, pullCommand := GetPullCommand(artifact.Name, artifact.Version,
string(packageType), registryURL) string(packageType), registryURL, setupDetailsAuthHeaderPrefix)
return &artifactapi.ArtifactMetadata{ return &artifactapi.ArtifactMetadata{
RegistryIdentifier: artifact.RepoName, RegistryIdentifier: artifact.RepoName,
Name: artifact.Name, Name: artifact.Name,
@ -140,13 +142,14 @@ func GetTagMetadata(
tags *[]types.TagMetadata, tags *[]types.TagMetadata,
image string, image string,
registryURL string, registryURL string,
setupDetailsAuthHeaderPrefix string,
) []artifactapi.ArtifactVersionMetadata { ) []artifactapi.ArtifactVersionMetadata {
artifactVersionMetadataList := []artifactapi.ArtifactVersionMetadata{} artifactVersionMetadataList := []artifactapi.ArtifactVersionMetadata{}
for _, tag := range *tags { for _, tag := range *tags {
modifiedAt := GetTimeInMs(tag.ModifiedAt) modifiedAt := GetTimeInMs(tag.ModifiedAt)
size := GetImageSize(tag.Size) size := GetImageSize(tag.Size)
digestCount := tag.DigestCount digestCount := tag.DigestCount
command := GetPullCommand(image, tag.Name, string(tag.PackageType), registryURL) command := GetPullCommand(image, tag.Name, string(tag.PackageType), registryURL, setupDetailsAuthHeaderPrefix)
packageType, err := toPackageType(string(tag.PackageType)) packageType, err := toPackageType(string(tag.PackageType))
downloadCount := tag.DownloadCount downloadCount := tag.DownloadCount
if err != nil { if err != nil {
@ -175,12 +178,13 @@ func GetAllArtifactResponse(
pageSize int, pageSize int,
rootIdentifier string, rootIdentifier string,
urlProvider url.Provider, urlProvider url.Provider,
setupDetailsAuthHeaderPrefix string,
) *artifactapi.ListArtifactResponseJSONResponse { ) *artifactapi.ListArtifactResponseJSONResponse {
var artifactMetadataList []artifactapi.ArtifactMetadata var artifactMetadataList []artifactapi.ArtifactMetadata
if artifacts == nil { if artifacts == nil {
artifactMetadataList = make([]artifactapi.ArtifactMetadata, 0) artifactMetadataList = make([]artifactapi.ArtifactMetadata, 0)
} else { } else {
artifactMetadataList = GetArtifactMetadata(ctx, *artifacts, rootIdentifier, urlProvider) artifactMetadataList = GetArtifactMetadata(ctx, *artifacts, rootIdentifier, urlProvider, setupDetailsAuthHeaderPrefix)
} }
pageCount := GetPageCount(count, pageSize) pageCount := GetPageCount(count, pageSize)
listArtifact := &artifactapi.ListArtifact{ listArtifact := &artifactapi.ListArtifact{
@ -206,12 +210,14 @@ func GetAllArtifactFilesResponse(
artifactName string, artifactName string,
version string, version string,
packageType artifactapi.PackageType, packageType artifactapi.PackageType,
setupDetailsAuthHeaderPrefix string,
) *artifactapi.FileDetailResponseJSONResponse { ) *artifactapi.FileDetailResponseJSONResponse {
var fileMetadataList []artifactapi.FileDetail var fileMetadataList []artifactapi.FileDetail
if files == nil { if files == nil {
fileMetadataList = make([]artifactapi.FileDetail, 0) fileMetadataList = make([]artifactapi.FileDetail, 0)
} else { } else {
fileMetadataList = GetArtifactFilesMetadata(files, registryURL, artifactName, version, packageType) fileMetadataList = GetArtifactFilesMetadata(files, registryURL, artifactName,
version, packageType, setupDetailsAuthHeaderPrefix)
} }
pageCount := GetPageCount(count, pageSize) pageCount := GetPageCount(count, pageSize)
return &artifactapi.FileDetailResponseJSONResponse{ return &artifactapi.FileDetailResponseJSONResponse{
@ -230,6 +236,7 @@ func GetArtifactFilesMetadata(
artifactName string, artifactName string,
version string, version string,
packageType artifactapi.PackageType, packageType artifactapi.PackageType,
setupDetailsAuthHeaderPrefix string,
) []artifactapi.FileDetail { ) []artifactapi.FileDetail {
var files []artifactapi.FileDetail var files []artifactapi.FileDetail
for _, file := range *metadata { for _, file := range *metadata {
@ -239,15 +246,17 @@ func GetArtifactFilesMetadata(
//nolint:exhaustive //nolint:exhaustive
switch packageType { switch packageType {
case artifactapi.PackageTypeGENERIC, artifactapi.PackageTypePYTHON, artifactapi.PackageTypeNPM: case artifactapi.PackageTypeGENERIC, artifactapi.PackageTypePYTHON, artifactapi.PackageTypeNPM:
downloadCommand = GetGenericArtifactFileDownloadCommand(registryURL, artifactName, version, filename) downloadCommand = GetGenericArtifactFileDownloadCommand(registryURL, artifactName,
version, filename, setupDetailsAuthHeaderPrefix)
case artifactapi.PackageTypeMAVEN: case artifactapi.PackageTypeMAVEN:
artifactName = strings.ReplaceAll(artifactName, ".", "/") artifactName = strings.ReplaceAll(artifactName, ".", "/")
artifactName = strings.ReplaceAll(artifactName, ":", "/") artifactName = strings.ReplaceAll(artifactName, ":", "/")
filePathPrefix = "/" + artifactName + "/" + version + "/" filePathPrefix = "/" + artifactName + "/" + version + "/"
filename = strings.Replace(file.Path, filePathPrefix, "", 1) filename = strings.Replace(file.Path, filePathPrefix, "", 1)
downloadCommand = GetMavenArtifactFileDownloadCommand(registryURL, artifactName, version, filename) downloadCommand = GetMavenArtifactFileDownloadCommand(registryURL, artifactName,
version, filename, setupDetailsAuthHeaderPrefix)
case artifactapi.PackageTypeRPM: case artifactapi.PackageTypeRPM:
downloadCommand = GetRPMArtifactFileDownloadCommand(registryURL, filename) downloadCommand = GetRPMArtifactFileDownloadCommand(registryURL, filename, setupDetailsAuthHeaderPrefix)
} }
files = append(files, artifactapi.FileDetail{ files = append(files, artifactapi.FileDetail{
Checksums: getCheckSums(file), Checksums: getCheckSums(file),
@ -325,9 +334,10 @@ func GetAllArtifactVersionResponse(
pageNumber int64, pageNumber int64,
pageSize int, pageSize int,
registryURL string, registryURL string,
setupDetailsAuthHeaderPrefix string,
) *artifactapi.ListArtifactVersionResponseJSONResponse { ) *artifactapi.ListArtifactVersionResponseJSONResponse {
artifactVersionMetadataList := GetTagMetadata( artifactVersionMetadataList := GetTagMetadata(
ctx, tags, image, registryURL, ctx, tags, image, registryURL, setupDetailsAuthHeaderPrefix,
) )
pageCount := GetPageCount(count, pageSize) pageCount := GetPageCount(count, pageSize)
listArtifactVersions := &artifactapi.ListArtifactVersion{ listArtifactVersions := &artifactapi.ListArtifactVersion{
@ -352,10 +362,10 @@ func GetNonOCIAllArtifactVersionResponse(
pageNumber int64, pageNumber int64,
pageSize int, pageSize int,
registryURL string, registryURL string,
setupDetailsAuthHeaderPrefix string,
) *artifactapi.ListArtifactVersionResponseJSONResponse { ) *artifactapi.ListArtifactVersionResponseJSONResponse {
artifactVersionMetadataList := GetNonOCIArtifactMetadata( artifactVersionMetadataList := GetNonOCIArtifactMetadata(
ctx, artifacts, image, registryURL, ctx, artifacts, image, registryURL, setupDetailsAuthHeaderPrefix)
)
pageCount := GetPageCount(count, pageSize) pageCount := GetPageCount(count, pageSize)
listArtifactVersions := &artifactapi.ListArtifactVersion{ listArtifactVersions := &artifactapi.ListArtifactVersion{
ItemCount: &count, ItemCount: &count,
@ -376,12 +386,13 @@ func GetNonOCIArtifactMetadata(
tags *[]types.NonOCIArtifactMetadata, tags *[]types.NonOCIArtifactMetadata,
image string, image string,
registryURL string, registryURL string,
setupDetailsAuthHeaderPrefix string,
) []artifactapi.ArtifactVersionMetadata { ) []artifactapi.ArtifactVersionMetadata {
artifactVersionMetadataList := []artifactapi.ArtifactVersionMetadata{} artifactVersionMetadataList := []artifactapi.ArtifactVersionMetadata{}
for _, tag := range *tags { for _, tag := range *tags {
modifiedAt := GetTimeInMs(tag.ModifiedAt) modifiedAt := GetTimeInMs(tag.ModifiedAt)
size := GetImageSize(tag.Size) size := GetImageSize(tag.Size)
command := GetPullCommand(image, tag.Name, string(tag.PackageType), registryURL) command := GetPullCommand(image, tag.Name, string(tag.PackageType), registryURL, setupDetailsAuthHeaderPrefix)
packageType, err := toPackageType(string(tag.PackageType)) packageType, err := toPackageType(string(tag.PackageType))
downloadCount := tag.DownloadCount downloadCount := tag.DownloadCount
if err != nil { if err != nil {

View File

@ -30,29 +30,30 @@ import (
// APIController simple struct. // APIController simple struct.
type APIController struct { type APIController struct {
ImageStore store.ImageRepository ImageStore store.ImageRepository
fileManager filemanager.FileManager fileManager filemanager.FileManager
BlobStore store.BlobRepository BlobStore store.BlobRepository
GenericBlobStore store.GenericBlobRepository GenericBlobStore store.GenericBlobRepository
RegistryRepository store.RegistryRepository RegistryRepository store.RegistryRepository
UpstreamProxyStore store.UpstreamProxyConfigRepository UpstreamProxyStore store.UpstreamProxyConfigRepository
TagStore store.TagRepository TagStore store.TagRepository
ManifestStore store.ManifestRepository ManifestStore store.ManifestRepository
CleanupPolicyStore store.CleanupPolicyRepository CleanupPolicyStore store.CleanupPolicyRepository
SpaceFinder interfaces.SpaceFinder SpaceFinder interfaces.SpaceFinder
tx dbtx.Transactor tx dbtx.Transactor
StorageDriver storagedriver.StorageDriver StorageDriver storagedriver.StorageDriver
URLProvider urlprovider.Provider URLProvider urlprovider.Provider
Authorizer authz.Authorizer Authorizer authz.Authorizer
AuditService audit.Service AuditService audit.Service
ArtifactStore store.ArtifactRepository ArtifactStore store.ArtifactRepository
WebhooksRepository store.WebhooksRepository WebhooksRepository store.WebhooksRepository
WebhooksExecutionRepository store.WebhooksExecutionRepository WebhooksExecutionRepository store.WebhooksExecutionRepository
RegistryMetadataHelper interfaces.RegistryMetadataHelper RegistryMetadataHelper interfaces.RegistryMetadataHelper
WebhookService webhook.ServiceInterface WebhookService webhook.ServiceInterface
ArtifactEventReporter registryevents.Reporter ArtifactEventReporter registryevents.Reporter
DownloadStatRepository store.DownloadStatRepository DownloadStatRepository store.DownloadStatRepository
RegistryIndexService index.Service RegistryIndexService index.Service
SetupDetailsAuthHeaderPrefix string
} }
func NewAPIController( func NewAPIController(
@ -79,30 +80,32 @@ func NewAPIController(
artifactEventReporter registryevents.Reporter, artifactEventReporter registryevents.Reporter,
downloadStatRepository store.DownloadStatRepository, downloadStatRepository store.DownloadStatRepository,
registryIndexService index.Service, registryIndexService index.Service,
setupDetailsAuthHeaderPrefix string,
) *APIController { ) *APIController {
return &APIController{ return &APIController{
fileManager: fileManager, fileManager: fileManager,
GenericBlobStore: genericBlobStore, GenericBlobStore: genericBlobStore,
BlobStore: blobStore, BlobStore: blobStore,
RegistryRepository: repositoryStore, RegistryRepository: repositoryStore,
UpstreamProxyStore: upstreamProxyStore, UpstreamProxyStore: upstreamProxyStore,
TagStore: tagStore, TagStore: tagStore,
ManifestStore: manifestStore, ManifestStore: manifestStore,
CleanupPolicyStore: cleanupPolicyStore, CleanupPolicyStore: cleanupPolicyStore,
ImageStore: imageStore, ImageStore: imageStore,
SpaceFinder: spaceFinder, SpaceFinder: spaceFinder,
StorageDriver: driver, StorageDriver: driver,
tx: tx, tx: tx,
URLProvider: urlProvider, URLProvider: urlProvider,
Authorizer: authorizer, Authorizer: authorizer,
AuditService: auditService, AuditService: auditService,
ArtifactStore: artifactStore, ArtifactStore: artifactStore,
WebhooksRepository: webhooksRepository, WebhooksRepository: webhooksRepository,
WebhooksExecutionRepository: webhooksExecutionRepository, WebhooksExecutionRepository: webhooksExecutionRepository,
RegistryMetadataHelper: registryMetadataHelper, RegistryMetadataHelper: registryMetadataHelper,
WebhookService: webhookService, WebhookService: webhookService,
ArtifactEventReporter: artifactEventReporter, ArtifactEventReporter: artifactEventReporter,
DownloadStatRepository: downloadStatRepository, DownloadStatRepository: downloadStatRepository,
RegistryIndexService: registryIndexService, RegistryIndexService: registryIndexService,
SetupDetailsAuthHeaderPrefix: setupDetailsAuthHeaderPrefix,
} }
} }

View File

@ -264,6 +264,7 @@ func TestCreateRegistry(t *testing.T) {
eventReporter, eventReporter,
nil, // downloadStatRepository. nil, // downloadStatRepository.
nil, // registryIndexService - not needed for this test. nil, // registryIndexService - not needed for this test.
"",
) )
}, },
}, },
@ -335,6 +336,7 @@ func TestCreateRegistry(t *testing.T) {
eventReporter, eventReporter,
nil, // nil, //
nil, // downloadStatRepository. nil, // downloadStatRepository.
"",
) )
}, },
}, },

View File

@ -131,7 +131,7 @@ func (c *APIController) GetArtifactFiles(
return artifact.GetArtifactFiles200JSONResponse{ return artifact.GetArtifactFiles200JSONResponse{
FileDetailResponseJSONResponse: *GetAllArtifactFilesResponse( FileDetailResponseJSONResponse: *GetAllArtifactFilesResponse(
fileMetadataList, count, reqInfo.pageNumber, reqInfo.limit, registryURL, img.Name, art.Version, fileMetadataList, count, reqInfo.pageNumber, reqInfo.limit, registryURL, img.Name, art.Version,
registry.PackageType), registry.PackageType, c.SetupDetailsAuthHeaderPrefix),
}, nil }, nil
default: default:
return artifact.GetArtifactFiles400JSONResponse{ return artifact.GetArtifactFiles400JSONResponse{

View File

@ -91,7 +91,7 @@ func (c *APIController) GetAllArtifacts(
} }
return artifact.GetAllArtifacts200JSONResponse{ return artifact.GetAllArtifacts200JSONResponse{
ListArtifactResponseJSONResponse: *GetAllArtifactResponse(ctx, artifacts, count, regInfo.pageNumber, regInfo.limit, ListArtifactResponseJSONResponse: *GetAllArtifactResponse(ctx, artifacts, count, regInfo.pageNumber, regInfo.limit,
regInfo.RootIdentifier, c.URLProvider), regInfo.RootIdentifier, c.URLProvider, c.SetupDetailsAuthHeaderPrefix),
}, nil }, nil
} }

View File

@ -130,6 +130,7 @@ func (c *APIController) GetAllArtifactVersions(
ListArtifactVersionResponseJSONResponse: *GetAllArtifactVersionResponse( ListArtifactVersionResponseJSONResponse: *GetAllArtifactVersionResponse(
ctx, tags, image, count, regInfo.pageNumber, regInfo.limit, ctx, tags, image, count, regInfo.pageNumber, regInfo.limit,
c.URLProvider.RegistryURL(ctx, regInfo.RootIdentifier, regInfo.RegistryIdentifier), c.URLProvider.RegistryURL(ctx, regInfo.RootIdentifier, regInfo.RegistryIdentifier),
c.SetupDetailsAuthHeaderPrefix,
), ),
}, nil }, nil
} }
@ -150,6 +151,7 @@ func (c *APIController) GetAllArtifactVersions(
ListArtifactVersionResponseJSONResponse: *GetNonOCIAllArtifactVersionResponse( ListArtifactVersionResponseJSONResponse: *GetNonOCIAllArtifactVersionResponse(
ctx, metadata, image, cnt, regInfo.pageNumber, regInfo.limit, ctx, metadata, image, cnt, regInfo.pageNumber, regInfo.limit,
c.URLProvider.RegistryURL(ctx, regInfo.RootIdentifier, regInfo.RegistryIdentifier), c.URLProvider.RegistryURL(ctx, regInfo.RootIdentifier, regInfo.RegistryIdentifier),
c.SetupDetailsAuthHeaderPrefix,
), ),
}, nil }, nil
} }

View File

@ -278,7 +278,7 @@ func (c *APIController) generateGenericClientSetupDetail(
header2 := "Upload Artifact" header2 := "Upload Artifact"
section2step1Header := "Run this curl command in your terminal to push the artifact." section2step1Header := "Run this curl command in your terminal to push the artifact."
//nolint:lll //nolint:lll
pushValue := "curl --location --request PUT '<HOSTNAME>/<ARTIFACT_NAME>/<VERSION>' \\\n--form 'filename=\"<FILENAME>\"' \\\n--form 'file=@\"<FILE_PATH>\"' \\\n--form 'description=\"<DESC>\"' \\\n--header 'x-api-key: <API_KEY>'" pushValue := "curl --location --request PUT '<HOSTNAME>/<ARTIFACT_NAME>/<VERSION>' \\\n--form 'filename=\"<FILENAME>\"' \\\n--form 'file=@\"<FILE_PATH>\"' \\\n--form 'description=\"<DESC>\"' \\\n--header '<AUTH_HEADER_PREFIX> <API_KEY>'"
section2step1Commands := []artifact.ClientSetupStepCommand{ section2step1Commands := []artifact.ClientSetupStepCommand{
{Label: &blankString, Value: &pushValue}, {Label: &blankString, Value: &pushValue},
} }
@ -299,7 +299,7 @@ func (c *APIController) generateGenericClientSetupDetail(
header3 := "Download Artifact" header3 := "Download Artifact"
section3step1Header := "Run this command in your terminal to download the artifact." section3step1Header := "Run this command in your terminal to download the artifact."
//nolint:lll //nolint:lll
pullValue := "curl --location '<HOSTNAME>/<ARTIFACT_NAME>/<VERSION>' \\\n--form 'filename=\"<FILENAME>\"' --header 'x-api-key: <API_KEY>' " + pullValue := "curl --location '<HOSTNAME>/<ARTIFACT_NAME>/<VERSION>' \\\n--form 'filename=\"<FILENAME>\"' --header '<AUTH_HEADER_PREFIX> <API_KEY>' " +
"-o <FILENAME>" "-o <FILENAME>"
section3step1Commands := []artifact.ClientSetupStepCommand{ section3step1Commands := []artifact.ClientSetupStepCommand{
{Label: &blankString, Value: &pullValue}, {Label: &blankString, Value: &pullValue},
@ -869,7 +869,7 @@ func (c *APIController) generateRpmClientSetupDetail(
Commands: &[]artifact.ClientSetupStepCommand{ Commands: &[]artifact.ClientSetupStepCommand{
{ {
//nolint:lll //nolint:lll
Value: utils.StringPtr("curl --location --request PUT '<REGISTRY_URL>/' \\\n--form 'file=@\"<FILE_PATH>\"' \\\n--header 'x-api-key: <API_KEY>'"), Value: utils.StringPtr("curl --location --request PUT '<REGISTRY_URL>/' \\\n--form 'file=@\"<FILE_PATH>\"' \\\n--header '<AUTH_HEADER_PREFIX> <API_KEY>'"),
}, },
}, },
}, },
@ -936,7 +936,7 @@ func (c *APIController) generateRpmClientSetupDetail(
Commands: &[]artifact.ClientSetupStepCommand{ Commands: &[]artifact.ClientSetupStepCommand{
{ {
//nolint:lll //nolint:lll
Value: utils.StringPtr("curl --location --request PUT '<REGISTRY_URL>/' \\\n--form 'file=@\"<FILE_PATH>\"' \\\n--header 'x-api-key: <API_KEY>'"), Value: utils.StringPtr("curl --location --request PUT '<REGISTRY_URL>/' \\\n--form 'file=@\"<FILE_PATH>\"' \\\n--header '<AUTH_HEADER_PREFIX> <API_KEY>'"),
}, },
}, },
}, },
@ -1264,13 +1264,13 @@ func (c *APIController) replacePlaceholdersInSection(
continue continue
} }
for j := range *st.Commands { for j := range *st.Commands {
replaceText(username, st, j, hostname, registryName, image, tag, registryURL, groupID, uploadURL) c.replaceText(username, st, j, hostname, registryName, image, tag, registryURL, groupID, uploadURL)
} }
} }
_ = clientSetupSection.FromClientSetupStepConfig(sec) _ = clientSetupSection.FromClientSetupStepConfig(sec)
} }
func replaceText( func (c *APIController) replaceText(
username string, username string,
st artifact.ClientSetupStep, st artifact.ClientSetupStep,
i int, i int,
@ -1282,6 +1282,10 @@ func replaceText(
groupID string, groupID string,
uploadURL string, uploadURL string,
) { ) {
if c.SetupDetailsAuthHeaderPrefix != "" {
(*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value,
"<AUTH_HEADER_PREFIX>", c.SetupDetailsAuthHeaderPrefix))
}
if username != "" { if username != "" {
(*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "<USERNAME>", username)) (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "<USERNAME>", username))
if (*st.Commands)[i].Label != nil { if (*st.Commands)[i].Label != nil {

View File

@ -364,7 +364,7 @@ func GetTagURL(artifact string, version string, registryURL string) string {
func GetPullCommand( func GetPullCommand(
image string, tag string, image string, tag string,
packageType string, registryURL string, packageType string, registryURL string, setupDetailsAuthHeaderPrefix string,
) string { ) string {
switch packageType { switch packageType {
case string(a.PackageTypeDOCKER): case string(a.PackageTypeDOCKER):
@ -372,7 +372,7 @@ func GetPullCommand(
case string(a.PackageTypeHELM): case string(a.PackageTypeHELM):
return GetHelmPullCommand(image, tag, registryURL) return GetHelmPullCommand(image, tag, registryURL)
case string(a.PackageTypeGENERIC): case string(a.PackageTypeGENERIC):
return GetGenericArtifactFileDownloadCommand(registryURL, image, tag, "<FILENAME>") return GetGenericArtifactFileDownloadCommand(registryURL, image, tag, "<FILENAME>", setupDetailsAuthHeaderPrefix)
case string(a.PackageTypePYTHON): case string(a.PackageTypePYTHON):
return GetPythonDownloadCommand(image, tag) return GetPythonDownloadCommand(image, tag)
case string(a.PackageTypeNPM): case string(a.PackageTypeNPM):
@ -443,16 +443,21 @@ func GetPythonDownloadCommand(artifact, version string) string {
return downloadCommand return downloadCommand
} }
func GetGenericArtifactFileDownloadCommand(regURL, artifact, version, filename string) string { func GetGenericArtifactFileDownloadCommand(
downloadCommand := "curl --location '<HOSTNAME>/<ARTIFACT>:<VERSION>:<FILENAME>' --header 'x-api-key: <API_KEY>'" + regURL, artifact, version, filename string,
setupDetailsAuthHeaderPrefix string,
) string {
downloadCommand := "curl --location '<HOSTNAME>/<ARTIFACT>:<VERSION>:<FILENAME>'" +
" --header '<AUTH_HEADER_PREFIX> <API_KEY>'" +
" -J -O" " -J -O"
// Replace the placeholders with the actual values // Replace the placeholders with the actual values
replacements := map[string]string{ replacements := map[string]string{
"<HOSTNAME>": regURL, "<HOSTNAME>": regURL,
"<ARTIFACT>": artifact, "<ARTIFACT>": artifact,
"<VERSION>": version, "<VERSION>": version,
"<FILENAME>": filename, "<FILENAME>": filename,
"<AUTH_HEADER_PREFIX>": setupDetailsAuthHeaderPrefix,
} }
for placeholder, value := range replacements { for placeholder, value := range replacements {
@ -462,12 +467,13 @@ func GetGenericArtifactFileDownloadCommand(regURL, artifact, version, filename s
return downloadCommand return downloadCommand
} }
func GetRPMArtifactFileDownloadCommand(regURL, filename string) string { func GetRPMArtifactFileDownloadCommand(regURL, filename string, setupDetailsAuthHeaderPrefix string) string {
downloadCommand := "curl --location '<HOSTNAME>/package<FILENAME>' --header 'x-api-key: <API_KEY>'" + downloadCommand := "curl --location '<HOSTNAME>/package<FILENAME>' --header '<AUTH_HEADER_PREFIX> <API_KEY>'" +
" -J -O" " -J -O"
replacements := map[string]string{ replacements := map[string]string{
"<HOSTNAME>": regURL, "<HOSTNAME>": regURL,
"<FILENAME>": filename, "<FILENAME>": filename,
"<AUTH_HEADER_PREFIX>": setupDetailsAuthHeaderPrefix,
} }
for placeholder, value := range replacements { for placeholder, value := range replacements {
@ -477,16 +483,20 @@ func GetRPMArtifactFileDownloadCommand(regURL, filename string) string {
return downloadCommand return downloadCommand
} }
func GetMavenArtifactFileDownloadCommand(regURL, artifact, version, filename string) string { func GetMavenArtifactFileDownloadCommand(
regURL, artifact, version, filename string,
setupDetailsAuthHeaderPrefix string,
) string {
downloadCommand := "curl --location '<HOSTNAME>/<ARTIFACT>/<VERSION>/<FILENAME>'" + downloadCommand := "curl --location '<HOSTNAME>/<ARTIFACT>/<VERSION>/<FILENAME>'" +
" --header 'x-api-key: <IDENTITY_TOKEN>' -O" " --header '<AUTH_HEADER_PREFIX> <IDENTITY_TOKEN>' -O"
// Replace the placeholders with the actual values // Replace the placeholders with the actual values
replacements := map[string]string{ replacements := map[string]string{
"<HOSTNAME>": regURL, "<HOSTNAME>": regURL,
"<ARTIFACT>": artifact, "<ARTIFACT>": artifact,
"<VERSION>": version, "<VERSION>": version,
"<FILENAME>": filename, "<FILENAME>": filename,
"<AUTH_HEADER_PREFIX>": setupDetailsAuthHeaderPrefix,
} }
for placeholder, value := range replacements { for placeholder, value := range replacements {

View File

@ -208,7 +208,7 @@ func TestGetPullCommand(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
result := metadata.GetPullCommand(tt.image, tt.tag, tt.pkgType, tt.baseURL) result := metadata.GetPullCommand(tt.image, tt.tag, tt.pkgType, tt.baseURL, "Authorization: Bearer")
assert.Equal(t, tt.expected, result) assert.Equal(t, tt.expected, result)
}) })
} }

View File

@ -35,6 +35,7 @@ import (
"github.com/harness/gitness/registry/services/index" "github.com/harness/gitness/registry/services/index"
registrywebhook "github.com/harness/gitness/registry/services/webhook" registrywebhook "github.com/harness/gitness/registry/services/webhook"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
) )
@ -79,6 +80,7 @@ func NewAPIHandler(
artifactEventReporter registryevents.Reporter, artifactEventReporter registryevents.Reporter,
downloadStatRepository store.DownloadStatRepository, downloadStatRepository store.DownloadStatRepository,
registryIndexService index.Service, registryIndexService index.Service,
gitnessConfig *types.Config,
) APIHandler { ) APIHandler {
r := chi.NewRouter() r := chi.NewRouter()
r.Use(audit.Middleware()) r.Use(audit.Middleware())
@ -109,6 +111,7 @@ func NewAPIHandler(
artifactEventReporter, artifactEventReporter,
downloadStatRepository, downloadStatRepository,
registryIndexService, registryIndexService,
gitnessConfig.Registry.SetupDetailsAuthHeaderPrefix,
) )
handler := artifact.NewStrictHandler(apiController, []artifact.StrictMiddlewareFunc{}) handler := artifact.NewStrictHandler(apiController, []artifact.StrictMiddlewareFunc{})

View File

@ -42,6 +42,7 @@ import (
"github.com/harness/gitness/registry/services/index" "github.com/harness/gitness/registry/services/index"
registrywebhook "github.com/harness/gitness/registry/services/webhook" registrywebhook "github.com/harness/gitness/registry/services/webhook"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/google/wire" "github.com/google/wire"
) )
@ -79,6 +80,7 @@ func APIHandlerProvider(
artifactEventReporter *registryevents.Reporter, artifactEventReporter *registryevents.Reporter,
downloadStatRepository store.DownloadStatRepository, downloadStatRepository store.DownloadStatRepository,
registryIndexService index.Service, registryIndexService index.Service,
gitnessConfig *types.Config,
) harness.APIHandler { ) harness.APIHandler {
return harness.NewAPIHandler( return harness.NewAPIHandler(
repoDao, repoDao,
@ -104,6 +106,7 @@ func APIHandlerProvider(
*artifactEventReporter, *artifactEventReporter,
downloadStatRepository, downloadStatRepository,
registryIndexService, registryIndexService,
gitnessConfig,
) )
} }

View File

@ -542,6 +542,7 @@ type Config struct {
TransactionTimeoutDuration time.Duration `envconfig:"GITNESS_REGISTRY_GARBAGE_COLLECTION_TRANSACTION_TIMEOUT_DURATION" default:"10s"` //nolint:lll TransactionTimeoutDuration time.Duration `envconfig:"GITNESS_REGISTRY_GARBAGE_COLLECTION_TRANSACTION_TIMEOUT_DURATION" default:"10s"` //nolint:lll
BlobsStorageTimeoutDuration time.Duration `envconfig:"GITNESS_REGISTRY_GARBAGE_COLLECTION_BLOB_STORAGE_TIMEOUT_DURATION" default:"5s"` //nolint:lll BlobsStorageTimeoutDuration time.Duration `envconfig:"GITNESS_REGISTRY_GARBAGE_COLLECTION_BLOB_STORAGE_TIMEOUT_DURATION" default:"5s"` //nolint:lll
} }
SetupDetailsAuthHeaderPrefix string `envconfig:"SETUP_DETAILS_AUTH_PREFIX" default:"Authorization: Bearer"`
} }
Instrumentation struct { Instrumentation struct {

View File

@ -84,7 +84,7 @@ export const MockGetGenericSetupClientOnRegistryConfigPageResponse = {
{ {
label: '', label: '',
value: value:
"curl --location --request PUT 'http://host.docker.internal:3000/generic/artifact-registry/generic-repo/\u003cARTIFACT_NAME\u003e/\u003cVERSION\u003e' \\\n--form 'filename=\"\u003cFILENAME\u003e\"' \\\n--form 'file=@\"\u003cFILE_PATH\u003e\"' \\\n--form 'description=\"\u003cDESC\u003e\"' \\\n--header 'x-api-key: \u003cAPI_KEY\u003e'" "curl --location --request PUT 'http://host.docker.internal:3000/generic/artifact-registry/generic-repo/\u003cARTIFACT_NAME\u003e/\u003cVERSION\u003e' \\\n--form 'filename=\"\u003cFILENAME\u003e\"' \\\n--form 'file=@\"\u003cFILE_PATH\u003e\"' \\\n--form 'description=\"\u003cDESC\u003e\"' \\\n--header 'Authorization: Bearer \u003cAPI_KEY\u003e'"
} }
], ],
header: 'Run this curl command in your terminal to push the artifact.', header: 'Run this curl command in your terminal to push the artifact.',
@ -101,7 +101,7 @@ export const MockGetGenericSetupClientOnRegistryConfigPageResponse = {
{ {
label: '', label: '',
value: value:
"curl --location 'http://host.docker.internal:3000/generic/artifact-registry/generic-repo/\u003cARTIFACT_NAME\u003e:\u003cVERSION\u003e:\u003cFILENAME\u003e' --header 'x-api-key: \u003cAPI_KEY\u003e' -J -O" "curl --location 'http://host.docker.internal:3000/generic/artifact-registry/generic-repo/\u003cARTIFACT_NAME\u003e:\u003cVERSION\u003e:\u003cFILENAME\u003e' --header 'Authorization: Bearer \u003cAPI_KEY\u003e' -J -O"
} }
], ],
header: 'Run this command in your terminal to download the artifact.', header: 'Run this command in your terminal to download the artifact.',

View File

@ -130,7 +130,7 @@ export const mockGenericArtifactFiles: FileDetailResponseResponse = {
], ],
createdAt: '1738258177381', createdAt: '1738258177381',
downloadCommand: downloadCommand:
"curl --location 'https://pkg.qa.harness.io/generic/iWnhltqOT7GFt7R-F_zP7Q/generic-registry/artifact:v1:image.png' --header 'x-api-key: \u003cAPI_KEY\u003e' -J -O", "curl --location 'https://pkg.qa.harness.io/generic/iWnhltqOT7GFt7R-F_zP7Q/generic-registry/artifact:v1:image.png' --header 'Authorization: Bearer \u003cAPI_KEY\u003e' -J -O",
name: 'image.png', name: 'image.png',
size: '170.18KB' size: '170.18KB'
}, },