128 lines
4.8 KiB
Go
128 lines
4.8 KiB
Go
package validator
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"browser.local/platform/domain"
|
|
)
|
|
|
|
const (
|
|
MaxArtifactChunkBytes = 1024 * 1024
|
|
MaxArtifactBytes = int64(512 * 1024 * 1024)
|
|
)
|
|
|
|
func ValidateArtifactTransferOpen(open domain.ArtifactTransferOpen) error {
|
|
var violations []string
|
|
violations = appendRequired(violations, "runEndpointId", open.RunEndpointID)
|
|
violations = appendRequired(violations, "sessionToken", open.SessionToken)
|
|
violations = appendRequired(violations, "artifactId", open.ArtifactID)
|
|
violations = appendRequired(violations, "ownerId", open.OwnerID)
|
|
violations = appendRequired(violations, "checksum", open.Checksum)
|
|
violations = appendRequired(violations, "idempotencyKey", open.IdempotencyKey)
|
|
if open.Direction != domain.ArtifactTransferDirectionUpload {
|
|
violations = append(violations, "direction must be upload")
|
|
}
|
|
if !validArtifactOwnerKind(open.OwnerKind) {
|
|
violations = append(violations, "ownerKind is invalid")
|
|
}
|
|
if open.OwnerKind != domain.ArtifactOwnerKindJob && open.OwnerKind != domain.ArtifactOwnerKindServerInstance {
|
|
violations = append(violations, "ownerKind must be job or server-instance for run uploads")
|
|
}
|
|
if open.SizeBytes <= 0 {
|
|
violations = append(violations, "sizeBytes must be positive")
|
|
}
|
|
if open.SizeBytes > MaxArtifactBytes {
|
|
violations = append(violations, fmt.Sprintf("sizeBytes must not exceed %d", MaxArtifactBytes))
|
|
}
|
|
if open.ChunkSizeBytes <= 0 {
|
|
violations = append(violations, "chunkSizeBytes must be positive")
|
|
}
|
|
if open.ChunkSizeBytes > MaxArtifactChunkBytes {
|
|
violations = append(violations, fmt.Sprintf("chunkSizeBytes must not exceed %d", MaxArtifactChunkBytes))
|
|
}
|
|
if open.Checksum != "" && !validSHA256Checksum(open.Checksum) {
|
|
violations = append(violations, "checksum must be sha256:<hex>")
|
|
}
|
|
return finish(violations)
|
|
}
|
|
|
|
func ValidateArtifactChunkUpload(chunk domain.ArtifactChunkUpload) error {
|
|
var violations []string
|
|
violations = appendRequired(violations, "runEndpointId", chunk.RunEndpointID)
|
|
violations = appendRequired(violations, "sessionToken", chunk.SessionToken)
|
|
violations = appendRequired(violations, "transferId", chunk.TransferID)
|
|
violations = appendRequired(violations, "artifactId", chunk.ArtifactID)
|
|
violations = appendRequired(violations, "checksum", chunk.Checksum)
|
|
if chunk.ChunkIndex < 0 {
|
|
violations = append(violations, "chunkIndex must not be negative")
|
|
}
|
|
if chunk.Offset < 0 {
|
|
violations = append(violations, "offset must not be negative")
|
|
}
|
|
if chunk.SizeBytes <= 0 {
|
|
violations = append(violations, "sizeBytes must be positive")
|
|
}
|
|
if chunk.SizeBytes > MaxArtifactChunkBytes {
|
|
violations = append(violations, fmt.Sprintf("sizeBytes must not exceed %d", MaxArtifactChunkBytes))
|
|
}
|
|
if len(chunk.Payload) == 0 {
|
|
violations = append(violations, "payload must not be empty")
|
|
}
|
|
if chunk.SizeBytes > 0 && len(chunk.Payload) != chunk.SizeBytes {
|
|
violations = append(violations, "sizeBytes must match payload size")
|
|
}
|
|
if chunk.Checksum != "" {
|
|
if !validSHA256Checksum(chunk.Checksum) {
|
|
violations = append(violations, "checksum must be sha256:<hex>")
|
|
} else if chunk.Checksum != BytesChecksum(chunk.Payload) {
|
|
violations = append(violations, "checksum does not match payload")
|
|
}
|
|
}
|
|
return finish(violations)
|
|
}
|
|
|
|
func ValidateArtifactTransferStatusQuery(query domain.ArtifactTransferStatusQuery) error {
|
|
var violations []string
|
|
violations = appendRequired(violations, "runEndpointId", query.RunEndpointID)
|
|
violations = appendRequired(violations, "sessionToken", query.SessionToken)
|
|
violations = appendRequired(violations, "transferId", query.TransferID)
|
|
violations = appendRequired(violations, "artifactId", query.ArtifactID)
|
|
return finish(violations)
|
|
}
|
|
|
|
func ValidateArtifactTransferComplete(complete domain.ArtifactTransferComplete) error {
|
|
var violations []string
|
|
violations = appendRequired(violations, "runEndpointId", complete.RunEndpointID)
|
|
violations = appendRequired(violations, "sessionToken", complete.SessionToken)
|
|
violations = appendRequired(violations, "transferId", complete.TransferID)
|
|
violations = appendRequired(violations, "artifactId", complete.ArtifactID)
|
|
violations = appendRequired(violations, "checksum", complete.Checksum)
|
|
if complete.SizeBytes <= 0 {
|
|
violations = append(violations, "sizeBytes must be positive")
|
|
}
|
|
if complete.Checksum != "" && !validSHA256Checksum(complete.Checksum) {
|
|
violations = append(violations, "checksum must be sha256:<hex>")
|
|
}
|
|
return finish(violations)
|
|
}
|
|
|
|
func BytesChecksum(payload []byte) string {
|
|
sum := sha256.Sum256(payload)
|
|
return "sha256:" + hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
func validSHA256Checksum(value string) bool {
|
|
if !strings.HasPrefix(value, "sha256:") {
|
|
return false
|
|
}
|
|
hexValue := strings.TrimPrefix(value, "sha256:")
|
|
if len(hexValue) != sha256.Size*2 {
|
|
return false
|
|
}
|
|
_, err := hex.DecodeString(hexValue)
|
|
return err == nil
|
|
}
|