mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-05-14 03:01:48 +00:00
Implement -audit-read option.
This commit is contained in:
40
src/audit.go
40
src/audit.go
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/kankanreno/go-snowflake"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
@@ -72,20 +73,49 @@ func (id AuditID) CompareTime(when time.Time) int {
|
||||
return cmp.Compare(idMillis, whenMillis)
|
||||
}
|
||||
|
||||
func EncodeAuditRecord(auditRecord *AuditRecord) (data []byte) {
|
||||
data, err := proto.MarshalOptions{Deterministic: true}.Marshal(auditRecord)
|
||||
func EncodeAuditRecord(record *AuditRecord) (data []byte) {
|
||||
data, err := proto.MarshalOptions{Deterministic: true}.Marshal(record)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func DecodeAuditRecord(data []byte) (auditRecord *AuditRecord, err error) {
|
||||
auditRecord = &AuditRecord{}
|
||||
err = proto.Unmarshal(data, auditRecord)
|
||||
func DecodeAuditRecord(data []byte) (record *AuditRecord, err error) {
|
||||
record = &AuditRecord{}
|
||||
err = proto.Unmarshal(data, record)
|
||||
return
|
||||
}
|
||||
|
||||
type AuditRecordScope int
|
||||
|
||||
const (
|
||||
AuditRecordComplete AuditRecordScope = iota
|
||||
AuditRecordNoManifest
|
||||
)
|
||||
|
||||
func AuditRecordJSON(record *AuditRecord, scope AuditRecordScope) []byte {
|
||||
switch scope {
|
||||
case AuditRecordComplete:
|
||||
// as-is
|
||||
case AuditRecordNoManifest:
|
||||
// trim the manifest
|
||||
newRecord := &AuditRecord{}
|
||||
proto.Merge(newRecord, record)
|
||||
newRecord.Manifest = nil
|
||||
record = newRecord
|
||||
}
|
||||
|
||||
json, err := protojson.MarshalOptions{
|
||||
Multiline: true,
|
||||
EmitDefaultValues: true,
|
||||
}.Marshal(record)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return json
|
||||
}
|
||||
|
||||
type auditedBackend struct {
|
||||
Backend
|
||||
}
|
||||
|
||||
74
src/main.go
74
src/main.go
@@ -174,6 +174,8 @@ func usage() {
|
||||
"git-pages [-config <file>|-no-config]\n")
|
||||
fmt.Fprintf(os.Stderr, "(admin) "+
|
||||
"git-pages {-run-migration <name>|-freeze-domain <domain>|-unfreeze-domain <domain>}\n")
|
||||
fmt.Fprintf(os.Stderr, "(audit) "+
|
||||
"git-pages {-audit-read <id>}\n")
|
||||
fmt.Fprintf(os.Stderr, "(info) "+
|
||||
"git-pages {-print-config-env-vars|-print-config}\n")
|
||||
fmt.Fprintf(os.Stderr, "(cli) "+
|
||||
@@ -207,32 +209,28 @@ func Main() {
|
||||
"prevent any site uploads to a given `domain`")
|
||||
unfreezeDomain := flag.String("unfreeze-domain", "",
|
||||
"allow site uploads to a `domain` again after it has been frozen")
|
||||
auditRead := flag.String("audit-read", "",
|
||||
"extract contents of audit record `id` to files '<id>-*'")
|
||||
flag.Parse()
|
||||
|
||||
var cliOperations int
|
||||
if *runMigration != "" {
|
||||
cliOperations += 1
|
||||
}
|
||||
if *getBlob != "" {
|
||||
cliOperations += 1
|
||||
}
|
||||
if *getManifest != "" {
|
||||
cliOperations += 1
|
||||
}
|
||||
if *getArchive != "" {
|
||||
cliOperations += 1
|
||||
}
|
||||
if *updateSite != "" {
|
||||
cliOperations += 1
|
||||
}
|
||||
if *freezeDomain != "" {
|
||||
cliOperations += 1
|
||||
}
|
||||
if *unfreezeDomain != "" {
|
||||
cliOperations += 1
|
||||
for _, selected := range []bool{
|
||||
*runMigration != "",
|
||||
*getBlob != "",
|
||||
*getManifest != "",
|
||||
*getArchive != "",
|
||||
*updateSite != "",
|
||||
*freezeDomain != "",
|
||||
*unfreezeDomain != "",
|
||||
*auditRead != "",
|
||||
} {
|
||||
if selected {
|
||||
cliOperations++
|
||||
}
|
||||
}
|
||||
if cliOperations > 1 {
|
||||
logc.Fatalln(ctx, "-get-blob, -get-manifest, -get-archive, -update-site, -freeze, and -unfreeze are mutually exclusive")
|
||||
logc.Fatalln(ctx, "-get-blob, -get-manifest, -get-archive, -update-site, "+
|
||||
"-freeze, -unfreeze, -audit-log, and -audit-read are mutually exclusive")
|
||||
}
|
||||
|
||||
if *configTomlPath != "" && *noConfig {
|
||||
@@ -301,7 +299,7 @@ func Main() {
|
||||
if err != nil {
|
||||
logc.Fatalln(ctx, err)
|
||||
}
|
||||
fmt.Fprintln(fileOutputArg(), ManifestDebugJSON(manifest))
|
||||
fmt.Fprintln(fileOutputArg(), string(ManifestJSON(manifest)))
|
||||
|
||||
case *getArchive != "":
|
||||
if backend, err = CreateBackend(&config.Storage); err != nil {
|
||||
@@ -402,9 +400,37 @@ func Main() {
|
||||
logc.Fatalln(ctx, err)
|
||||
}
|
||||
if freeze {
|
||||
log.Println("frozen")
|
||||
logc.Println(ctx, "frozen")
|
||||
} else {
|
||||
log.Println("thawed")
|
||||
logc.Println(ctx, "thawed")
|
||||
}
|
||||
|
||||
case *auditRead != "":
|
||||
if backend, err = CreateBackend(&config.Storage); err != nil {
|
||||
logc.Fatalln(ctx, err)
|
||||
}
|
||||
|
||||
id, err := ParseAuditID(*auditRead)
|
||||
if err != nil {
|
||||
logc.Fatalln(ctx, err)
|
||||
}
|
||||
|
||||
record, err := backend.QueryAuditLog(ctx, id)
|
||||
if err != nil {
|
||||
logc.Fatalln(ctx, err)
|
||||
}
|
||||
|
||||
errEvent := os.WriteFile(fmt.Sprintf("%s-event.json", id),
|
||||
AuditRecordJSON(record, AuditRecordNoManifest), 0o400)
|
||||
errManifest := os.WriteFile(fmt.Sprintf("%s-manifest.json", id),
|
||||
ManifestJSON(record.Manifest), 0o400)
|
||||
fileArchive, errArchive := os.OpenFile(fmt.Sprintf("%s-archive.tar", id),
|
||||
os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o400)
|
||||
if err = errors.Join(errEvent, errManifest, errArchive); err != nil {
|
||||
logc.Fatalln(ctx, err)
|
||||
}
|
||||
if err = CollectTar(ctx, fileArchive, record.Manifest, ManifestMetadata{}); err != nil {
|
||||
logc.Fatalln(ctx, err)
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@@ -139,15 +139,15 @@ func GetProblemReport(manifest *Manifest) []string {
|
||||
return report
|
||||
}
|
||||
|
||||
func ManifestDebugJSON(manifest *Manifest) string {
|
||||
result, err := protojson.MarshalOptions{
|
||||
func ManifestJSON(manifest *Manifest) []byte {
|
||||
json, err := protojson.MarshalOptions{
|
||||
Multiline: true,
|
||||
EmitDefaultValues: true,
|
||||
}.Marshal(manifest)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(result)
|
||||
return json
|
||||
}
|
||||
|
||||
var ErrSymlinkLoop = errors.New("symbolic link loop")
|
||||
|
||||
@@ -188,7 +188,7 @@ func getPage(w http.ResponseWriter, r *http.Request) error {
|
||||
w.Header().Add("Last-Modified", lastModified)
|
||||
w.Header().Add("ETag", fmt.Sprintf("\"%s-manifest\"", metadata.ETag))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(ManifestDebugJSON(manifest)))
|
||||
w.Write(ManifestJSON(manifest))
|
||||
return nil
|
||||
|
||||
case metadataPath == "archive.tar" && config.Feature("archive-site"):
|
||||
|
||||
@@ -74,7 +74,7 @@ func Update(
|
||||
status = "unchanged"
|
||||
}
|
||||
if storedManifest.Commit != nil {
|
||||
logc.Printf(ctx, "update %s ok: %s %s", webRoot, status, *storedManifest.Commit)
|
||||
logc.Printf(ctx, "update %s ok: %s %s", webRoot, *storedManifest.Commit, status)
|
||||
} else {
|
||||
logc.Printf(ctx, "update %s ok: %s", webRoot, status)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user