1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
package gitalyssh
import (
"context"
"fmt"
"math/rand"
"os"
"path/filepath"
"strings"
"time"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"gitlab.com/gitlab-org/gitaly/internal/config"
"gitlab.com/gitlab-org/gitaly/internal/helper"
"gitlab.com/gitlab-org/gitaly/internal/metadata/featureflag"
gitaly_x509 "gitlab.com/gitlab-org/gitaly/internal/x509"
"gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
"gitlab.com/gitlab-org/labkit/correlation"
"gitlab.com/gitlab-org/labkit/tracing"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var (
envInjector = tracing.NewEnvInjector()
correlationIDRand = rand.New(rand.NewSource(time.Now().UnixNano()))
)
func UploadPackEnv(ctx context.Context, req *gitalypb.SSHUploadPackRequest) ([]string, error) {
env, err := commandEnv(ctx, req.Repository.StorageName, "upload-pack", req)
if err != nil {
return nil, err
}
return envInjector(ctx, env), nil
}
func commandEnv(ctx context.Context, storageName, command string, message proto.Message) ([]string, error) {
var pbMarshaler jsonpb.Marshaler
payload, err := pbMarshaler.MarshalToString(message)
if err != nil {
return nil, status.Errorf(codes.Internal, "commandEnv: marshalling payload failed: %v", err)
}
serversInfo, err := helper.ExtractGitalyServers(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "commandEnv: extracting Gitaly servers: %v", err)
}
storageInfo, ok := serversInfo[storageName]
if !ok {
return nil, status.Errorf(codes.InvalidArgument, "commandEnv: no storage info for %s", storageName)
}
address := storageInfo["address"]
if address == "" {
return nil, status.Errorf(codes.InvalidArgument, "commandEnv: empty gitaly address")
}
token := storageInfo["token"]
featureFlagPairs := featureflag.AllFlags(ctx)
return []string{
fmt.Sprintf("GITALY_PAYLOAD=%s", payload),
fmt.Sprintf("GIT_SSH_COMMAND=%s %s", gitalySSHPath(), command),
fmt.Sprintf("GITALY_ADDRESS=%s", address),
fmt.Sprintf("GITALY_TOKEN=%s", token),
fmt.Sprintf("GITALY_FEATUREFLAGS=%s", strings.Join(featureFlagPairs, ",")),
fmt.Sprintf("CORRELATION_ID=%s", getCorrelationID(ctx)),
// Pass through the SSL_CERT_* variables that indicate which
// system certs to trust
fmt.Sprintf("%s=%s", gitaly_x509.SSLCertDir, os.Getenv(gitaly_x509.SSLCertDir)),
fmt.Sprintf("%s=%s", gitaly_x509.SSLCertFile, os.Getenv(gitaly_x509.SSLCertFile)),
}, nil
}
func gitalySSHPath() string {
return filepath.Join(config.Config.BinDir, "gitaly-ssh")
}
func getCorrelationID(ctx context.Context) string {
correlationID := correlation.ExtractFromContext(ctx)
if correlationID != "" {
return correlationID
}
correlationID, _ = correlation.RandomID()
if correlationID == "" {
source := []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
correlationIDRand.Shuffle(len(source), func(i, j int) { source[i], source[j] = source[j], source[i] })
return correlationID[:32]
}
return correlationID
}
|