Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2c82308
audit_log_stream
amreshh Feb 23, 2026
754bdee
example added for azure blob storage, accessors re-generated / openap…
amreshh Feb 23, 2026
948070d
feature for api. and /api
amreshh Feb 23, 2026
f37e406
Merge branch 'master' into master
amreshh Feb 26, 2026
55149e2
fix: linting issues
amreshh Feb 26, 2026
72a5150
Merge branch 'master' into master
amreshh Feb 26, 2026
94e746b
Merge branch 'master' into master
amreshh Feb 27, 2026
84f5b25
Update github/enterprise_audit_log_stream.go
amreshh Feb 27, 2026
cf3de75
Update github/enterprise_audit_log_stream.go
amreshh Feb 27, 2026
f7e95dd
test: added testcases for enterprise_audit_log_stream
amreshh Feb 27, 2026
2e805cc
Merge branch 'master' into master
amreshh Feb 27, 2026
4e5e90e
Merge branch 'master' into master
amreshh Feb 28, 2026
246e60b
Update example/auditlogstream/main.go
amreshh Feb 28, 2026
63eda1c
Update example/auditlogstream/main.go
amreshh Feb 28, 2026
cdf7a8b
Update github/enterprise_audit_log_stream.go
amreshh Feb 28, 2026
3ff5342
Update github/enterprise_audit_log_stream.go
amreshh Feb 28, 2026
46bb884
Update github/enterprise_audit_log_stream.go
amreshh Feb 28, 2026
2321b8a
Update github/enterprise_audit_log_stream.go
amreshh Feb 28, 2026
5af1dc0
Merge branch 'master' into master
amreshh Mar 1, 2026
eb191dd
fix: example/auditlogstream
amreshh Feb 28, 2026
4c17774
fix: struct fields for audit log stream
amreshh Mar 1, 2026
9d91f24
refactor: inline vars in audit log stream constructor
amreshh Mar 1, 2026
471ca8c
Apply suggestion from @alexandear
amreshh Mar 1, 2026
9cd1bf4
fix: update CreateAuditLogStream
amreshh Mar 1, 2026
71aad8a
Update github/enterprise_audit_log_stream.go
amreshh Mar 1, 2026
73109b3
Update github/enterprise_audit_log_stream_test.go
amreshh Mar 1, 2026
eaa4cde
refactor: unit tests for audit log stream / usage of value params ins…
amreshh Mar 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions example/auditlogstream/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
// Copyright 2026 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The auditlogstream command demonstrates managing enterprise audit log
// streams for Azure Blob Storage using the go-github library.
//
// The GitHub API base URL is read from the GITHUB_API_URL environment
// variable. When running inside a GitHub Actions workflow this is set
// automatically.
//
// Usage — create:
//
// export GITHUB_AUTH_TOKEN=<your token>
// export GITHUB_API_URL=https://api.<domain>.ghe.com/ or https://domain/api/v3/
// go run main.go create \
// -enterprise=my-enterprise \
// -container=my-container \
// -sas-url=<plain-text-sas-url>
//
// Usage — delete:
//
// export GITHUB_AUTH_TOKEN=<your token>
// export GITHUB_API_URL=https://api.<domain>.ghe.com/ or https://domain/api/v3/
// go run main.go delete \
// -enterprise=my-enterprise \
// -stream-id=42
package main

import (
"context"
"crypto/rand"
"encoding/base64"
"flag"
"fmt"
"log"
"os"

"github.com/google/go-github/v84/github"
"golang.org/x/crypto/nacl/box"
)

// encryptSecret encrypts a plain-text secret using libsodium's sealed box
// (crypto_box_seal), which is what GitHub's API expects for encrypted credentials.
func encryptSecret(publicKeyB64, secret string) (string, error) {
publicKeyBytes, err := base64.StdEncoding.DecodeString(publicKeyB64)
if err != nil {
return "", fmt.Errorf("decoding public key: %w", err)
}
if len(publicKeyBytes) != 32 {
return "", fmt.Errorf("public key must be 32 bytes, got %v", len(publicKeyBytes))
}
publicKey := [32]byte(publicKeyBytes)

encrypted, err := box.SealAnonymous(nil, []byte(secret), &publicKey, rand.Reader)
if err != nil {
return "", fmt.Errorf("encrypting secret: %w", err)
}

return base64.StdEncoding.EncodeToString(encrypted), nil
}

func main() {
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "Usage: %v <create|delete> [flags]\n", os.Args[0])
os.Exit(1)
}

switch os.Args[1] {
case "create":
runCreate(os.Args[2:])
case "delete":
runDelete(os.Args[2:])
default:
fmt.Fprintf(os.Stderr, "Unknown command %q. Must be one of: create, delete\n", os.Args[1])
os.Exit(1)
}
}

// newFlagSet creates a FlagSet with the common -enterprise flag pre-registered.
func newFlagSet(name string) (*flag.FlagSet, *string) {
fs := flag.NewFlagSet(name, flag.ExitOnError)
enterprise := fs.String("enterprise", "", "Enterprise slug (required).")
return fs, enterprise
}

// parseAndInit parses the FlagSet, validates the enterprise flag, reads
// environment variables, and returns a ready-to-use context, client, and
// enterprise slug.
func parseAndInit(fs *flag.FlagSet, enterprise *string, args []string) (context.Context, *github.Client, string) {
if err := fs.Parse(args); err != nil {
log.Fatalf("Error parsing flags: %v", err)
}

requireFlag("enterprise", *enterprise)

token := requireEnv("GITHUB_AUTH_TOKEN")
apiURL := requireEnv("GITHUB_API_URL")

return context.Background(), newClient(token, apiURL), *enterprise
}

func runCreate(args []string) {
fs, enterprise := newFlagSet("create")
container := fs.String("container", "", "Azure Blob Storage container name (required).")
sasURL := fs.String("sas-url", "", "Plain-text Azure SAS URL to encrypt and submit (required).")
enabled := fs.Bool("enabled", true, "Whether the stream should be enabled immediately.")

ctx, client, ent := parseAndInit(fs, enterprise, args)
requireFlag("container", *container)
requireFlag("sas-url", *sasURL)

streamKey, _, err := client.Enterprise.GetAuditLogStreamKey(ctx, ent)
if err != nil {
log.Fatalf("Error fetching audit log stream key: %v", err)
}
fmt.Printf("Retrieved stream key ID: %v\n", streamKey.KeyID)

encryptedSASURL, err := encryptSecret(streamKey.Key, *sasURL)
if err != nil {
log.Fatalf("Error encrypting SAS URL: %v", err)
}
fmt.Println("SAS URL encrypted successfully.")

config := github.NewAzureBlobStreamConfig(*enabled, &github.AzureBlobConfig{
KeyID: streamKey.KeyID,
Container: *container,
EncryptedSASURL: encryptedSASURL,
})

stream, _, err := client.Enterprise.CreateAuditLogStream(ctx, ent, *config)
if err != nil {
log.Fatalf("Error creating audit log stream: %v", err)
}

fmt.Println("Successfully created audit log stream:")
fmt.Printf(" ID: %v\n", stream.ID)
fmt.Printf(" Type: %v\n", stream.StreamType)
fmt.Printf(" Enabled: %v\n", stream.Enabled)
fmt.Printf(" Created at: %v\n", stream.CreatedAt)
}

func runDelete(args []string) {
fs, enterprise := newFlagSet("delete")
streamID := fs.Int64("stream-id", 0, "ID of the audit log stream to delete (required).")

ctx, client, ent := parseAndInit(fs, enterprise, args)
requireIntFlag("stream-id", *streamID)

_, err := client.Enterprise.DeleteAuditLogStream(ctx, ent, *streamID)
if err != nil {
log.Fatalf("Error deleting audit log stream: %v", err)
}

fmt.Printf("Successfully deleted audit log stream %v.\n", *streamID)
}

func newClient(token, apiURL string) *github.Client {
client, err := github.NewClient(nil).WithAuthToken(token).WithEnterpriseURLs(apiURL, apiURL)
if err != nil {
log.Fatalf("Error creating GitHub client: %v", err)
}
return client
}

func requireEnv(name string) string {
val := os.Getenv(name)
if val == "" {
log.Fatalf("environment variable %v is not set", name)
}
return val
}

func requireFlag(name, val string) {
if val == "" {
log.Fatalf("flag -%v is required", name)
}
}

func requireIntFlag(name string, val int64) {
if val == 0 {
log.Fatalf("flag -%v is required", name)
}
}
Loading
Loading