in internal/collectiondefinition/gcs.go [72:184]
func fetchFromGCS(ctx context.Context, opts FetchOptions) *cdpb.CollectionDefinition {
bucketName := bucketEnvMap[opts.Env]
// Do not verify the connection to the Cloud Storage bucket.
// Public access is enabled for the downloaded files.
connectParams := &storage.ConnectParameters{
StorageClient: opts.Client,
BucketName: bucketName,
UserAgent: configuration.StorageAgentName(),
}
bh, ok := storage.ConnectToBucket(ctx, connectParams)
if !ok {
return nil
}
// Download the collection definition JSON file.
// From the Google Cloud Storage docs:
// Typically, a Reader computes the CRC of the downloaded content
// and compares it to the stored CRC, returning an error from Read
// if there is a mismatch.
cdJSON, err := opts.CreateTemp("", "collection-definition.*.json")
if err != nil {
log.CtxLogger(ctx).Warnw("Could not create temporary JSON file", "error", err)
return nil
}
defer os.Remove(cdJSON.Name())
defer cdJSON.Close()
rw1 := storage.ReadWriter{
Writer: cdJSON,
BucketHandle: bh,
Copier: io.Copy,
BucketName: bucketName,
ObjectName: "sapagent/collection-definition/collection_definition.json",
MaxRetries: 1,
ParallelDownloadConnectParams: connectParams,
}
if _, err = rw1.Download(ctx); err != nil {
log.CtxLogger(ctx).Warnw("Could not download from cloud storage", "objectName", rw1.ObjectName, "error", err)
return nil
}
// Download the signature file.
cdSignature, err := opts.CreateTemp("", "collection-definition.*.signature")
if err != nil {
log.CtxLogger(ctx).Warnw("Could not create temporary signature file", "error", err)
return nil
}
defer os.Remove(cdSignature.Name())
defer cdSignature.Close()
rw2 := storage.ReadWriter{
Writer: cdSignature,
BucketHandle: bh,
Copier: io.Copy,
BucketName: bucketName,
ObjectName: "sapagent/collection-definition/collection_definition.signature",
MaxRetries: 1,
ParallelDownloadConnectParams: connectParams,
}
if _, err = rw2.Download(ctx); err != nil {
log.CtxLogger(ctx).Warnw("Could not download from cloud storage", "objectName", rw2.ObjectName, "error", err)
return nil
}
// Verify using the public key embedded in the agent.
cdPub, err := opts.CreateTemp("", "public.*.pem")
if err != nil {
log.CtxLogger(ctx).Warnw("Could not create temporary public key file", "error", err)
return nil
}
pkey := pubkey
if opts.Env == cpb.TargetEnvironment_DEVELOPMENT || opts.Env == cpb.TargetEnvironment_INTEGRATION {
pkey = pubkeyDev
}
if _, err = cdPub.Write(pkey); err != nil {
log.CtxLogger(ctx).Warnw("Could not write public key to temp file", "error", err)
return nil
}
defer os.Remove(cdPub.Name())
defer cdPub.Close()
if opts.OSType == "windows" {
// TODO: Windows verification of downloaded content
log.CtxLogger(ctx).Warn("Windows signature verification is not supported")
return nil
}
result := opts.Execute(ctx, commandlineexecutor.Params{
Executable: "openssl",
ArgsToSplit: fmt.Sprintf("dgst -sha256 -verify %s -signature %s %s", cdPub.Name(), cdSignature.Name(), cdJSON.Name()),
})
if strings.TrimSpace(result.StdOut) != "Verified OK" {
log.CtxLogger(ctx).Warnw("Could not verify downloaded content for collection definition", "stdout", result.StdOut, "stderr", result.StdErr)
return nil
}
// Read and unmarshal the file as a collection definition.
stat, err := cdJSON.Stat()
if err != nil {
log.CtxLogger(ctx).Warn(err)
return nil
}
b := make([]byte, stat.Size())
if _, err = cdJSON.ReadAt(b, 0); err != nil && err != io.EOF {
log.CtxLogger(ctx).Warn(err)
return nil
}
cd, err := unmarshal(b)
if err != nil {
log.CtxLogger(ctx).Warn(err)
return nil
}
log.CtxLogger(ctx).Info("Successfully downloaded and verified collection definition")
return cd
}