Skip to content

Commit

Permalink
Merge branch 'devel' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
HilkopterBob authored Oct 29, 2024
2 parents 3ad2709 + 127078b commit 18456f8
Show file tree
Hide file tree
Showing 54 changed files with 2,950 additions and 1,035 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-docker-container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ jobs:
with:
push: true
tags: hilkopterbob/packagelock:latest
file: tools/Dockerfile
build-args: |
APP_VERSION=${{ github.event.release.tag_name }}
2 changes: 1 addition & 1 deletion .github/workflows/nightly_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ jobs:
gh release upload nightly \
release/packagelock-${{ env.APP_VERSION }}-linux-amd64-nightly.tar.gz \
release/packagelock-${{ env.APP_VERSION }}-linux-amd64-nightly.tar.gz.md5 \
--clobber
--clobber
18 changes: 18 additions & 0 deletions .github/workflows/publish-wiki.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Publish wiki
on:
push:
branches: [devel]
paths:
- wiki/**
- .github/workflows/publish-wiki.yml
concurrency:
group: publish-wiki
cancel-in-progress: true
permissions:
contents: write
jobs:
publish-wiki:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Andrew-Chen-Wang/github-wiki-action@v4
1 change: 1 addition & 0 deletions .github/workflows/unstable-build-docker-container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ jobs:
uses: docker/build-push-action@v6
with:
push: true
file: tools/Dockerfile-tracing
tags: hilkopterbob/packagelock:unstable-${{ github.head_ref || github.ref_name }}
695 changes: 674 additions & 21 deletions LICENSE

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/HilkopterBob/PackageLock/.github%2Fworkflows%2Frun-tests.yml)
![GitHub Actions Workflow Status](https://github.com/hilkopterbob/packagelock/actions/workflows/test-build.yml/badge.svg)
![GitHub Actions Workflow Status](https://github.com/hilkopterbob/packagelock/actions/workflows/release_tag.yml/badge.svg)
![GitHub Actions Workflow Status](https://github.com/hilkopterbob/packagelock/actions/workflows/golangci-lint.yml/badge.svg)
![GitHub Actions Workflow Status](https://github.com/hilkopterbob/packagelock/actions/workflows/build-docker-container.yml/badge.svg)
![GitHub Actions Workflow Status](https://github.com/hilkopterbob/packagelock/actions/workflows/unstable-build-docker-container.yml/badge.svg)
Expand Down
74 changes: 49 additions & 25 deletions certs/generate-certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,34 @@ import (
"encoding/pem"
"math/big"
"os"
"packagelock/logger"
"time"

"go.uber.org/fx"
"go.uber.org/zap"
)

// CreateSelfSignedCert generates a self-signed RSA certificate and private key
func CreateSelfSignedCert(certFile, keyFile string) error {
type CertGeneratorParams struct {
fx.In

Logger *zap.Logger
}

type CertGenerator struct {
logger *zap.Logger
}

func NewCertGenerator(params CertGeneratorParams) *CertGenerator {
return &CertGenerator{
logger: params.Logger,
}
}

// CreateSelfSignedCert generates a self-signed RSA certificate and private key.
func (cg *CertGenerator) CreateSelfSignedCert(certFile, keyFile string) error {
// Generate a private key using RSA (2048-bit key size)
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
logger.Logger.Warnf("failed to generate private key: %v", err)
cg.logger.Warn("Failed to generate private key", zap.Error(err))
return err
}

Expand All @@ -27,7 +45,7 @@ func CreateSelfSignedCert(certFile, keyFile string) error {

serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
if err != nil {
logger.Logger.Warnf("failed to generate serial number: %v", err)
cg.logger.Warn("Failed to generate serial number", zap.Error(err))
return err
}

Expand All @@ -43,58 +61,64 @@ func CreateSelfSignedCert(certFile, keyFile string) error {
BasicConstraintsValid: true,
}

// Ensure the "certs" directory exists
err = os.MkdirAll("certs/", os.ModePerm)
if err != nil {
cg.logger.Fatal("Cannot create 'certs/' directory", zap.Error(err))
return err
}

// Generate a self-signed certificate using the RSA private key
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
logger.Logger.Warnf("failed to create certificate: %v", err)
cg.logger.Warn("Failed to create certificate", zap.Error(err))
return err
}

// Save the certificate to certFile
certOut, err := os.Create(certFile)
if err != nil {
logger.Logger.Warnf("failed to open cert.pem for writing: %v", err)
cg.logger.Warn("Failed to open cert.pem for writing", zap.Error(err))
return err
}

// INFO: If the parrent throws an err and this defer is called
// and fileOut.Close() throws an error to, the original error will be overwritten.
defer func() {
deferredErr := certOut.Close()
if deferredErr != nil {
logger.Logger.Warnf("Cannot close Cert File, got: %s", deferredErr)
return
if err := certOut.Close(); err != nil {
cg.logger.Warn("Cannot close certificate file", zap.Error(err))
}
}()

if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certDER}); err != nil {
logger.Logger.Warnf("failed to write certificate to cert.pem: %v", err)
cg.logger.Warn("Failed to write certificate to file", zap.Error(err))
return err
}

// Save the RSA private key to keyFile
keyOut, err := os.Create(keyFile)
if err != nil {
logger.Logger.Warnf("failed to open key.pem for writing: %v", err)
cg.logger.Warn("Failed to open key.pem for writing", zap.Error(err))
return err
}

// INFO: If the parrent throws an err and this defer is called
// and fileOut.Close() throws an error to, the original error will be overwritten.
defer func() {
deferredErr := keyOut.Close()
if deferredErr != nil {
logger.Logger.Warnf("Cannot close Cert File, got: %s", deferredErr)
return
if err := keyOut.Close(); err != nil {
cg.logger.Warn("Cannot close key file", zap.Error(err))
}
}()

// Marshal the RSA private key
privBytes := x509.MarshalPKCS1PrivateKey(priv)
if err := pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: privBytes}); err != nil {
logger.Logger.Warnf("failed to write private key to key.pem: %v", err)
cg.logger.Warn("Failed to write private key to file", zap.Error(err))
return err
}

logger.Logger.Infof("Successfully created self-signed RSA certificate and private key.\n%s \n%s", certFile, keyFile)
cg.logger.Info("Successfully created self-signed RSA certificate and private key",
zap.String("certFile", certFile),
zap.String("keyFile", keyFile),
)
return nil
}

// Module exports the certs module.
var Module = fx.Options(
fx.Provide(NewCertGenerator),
)
171 changes: 171 additions & 0 deletions cmd/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package cmd

import (
"context"
"fmt"
"os"
"packagelock/certs"
"packagelock/config"
"packagelock/db"
"packagelock/logger"
"packagelock/structs"
"packagelock/tracing"
"time"

configPkg "packagelock/config"

"github.com/google/uuid"
"github.com/k0kubun/pp"
"github.com/sethvargo/go-password/password"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/surrealdb/surrealdb.go"
"go.uber.org/fx"
"go.uber.org/zap"
"golang.org/x/crypto/bcrypt"
)

func NewGenerateCmd() *cobra.Command {
generateCmd := &cobra.Command{
Use: "generate [certs|config|admin]",
Short: "Generate certificates, configuration files, or an admin",
Long: "Generate certificates, configuration files, or an admin user required by the application.",
Args: cobra.ExactValidArgs(1),

Check failure on line 33 in cmd/generate.go

View workflow job for this annotation

GitHub Actions / lint

SA1019: cobra.ExactValidArgs is deprecated: use MatchAll(ExactArgs(n), OnlyValidArgs) instead (staticcheck)
ValidArgs: []string{"certs", "config", "admin"},
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
fmt.Println("Please specify an argument: certs, config, or admin.")
return
}
switch args[0] {
case "certs":
app := fx.New(
fx.Provide(func() string { return "Command Runner" }),
logger.Module,
configPkg.Module,
certs.Module,
tracing.Module,
fx.Invoke(runGenerateCerts),
)

if err := app.Start(context.Background()); err != nil {
fmt.Println("Failed to start application for certificate generation:", err)
os.Exit(1)
}

if err := app.Stop(context.Background()); err != nil {
fmt.Println("Failed to stop application after certificate generation:", err)
os.Exit(1)
}
os.Exit(0)
case "config":
app := fx.New(
fx.Provide(func() string { return "Command Runner" }),
certs.Module,
logger.Module,
configPkg.Module,
tracing.Module,
fx.Invoke(runGenerateConfig),
)

if err := app.Start(context.Background()); err != nil {
fmt.Println("Failed to start application for config generation:", err)
os.Exit(1)
}

if err := app.Stop(context.Background()); err != nil {
fmt.Println("Failed to stop application after config generation:", err)
os.Exit(1)
}
os.Exit(0)
case "admin":
app := fx.New(
fx.Provide(func() string { return "Command Runner" }),
certs.Module,
config.Module,
logger.Module,
db.Module,
tracing.Module,
fx.Invoke(runGenerateAdmin),
)

if err := app.Start(context.Background()); err != nil {
fmt.Println("Failed to start application for admin generation:", err)
os.Exit(1)
}

if err := app.Stop(context.Background()); err != nil {
fmt.Println("Failed to stop application after admin generation:", err)
os.Exit(1)
}
os.Exit(0)
default:
fmt.Println("Invalid argument. Use 'certs', 'config', or 'admin'.")
}
},
}

return generateCmd
}

func runGenerateCerts(certGen *certs.CertGenerator, logger *zap.Logger, config *viper.Viper) {
err := certGen.CreateSelfSignedCert(
config.GetString("network.ssl-config.certificatepath"),
config.GetString("network.ssl-config.privatekeypath"),
)
if err != nil {
fmt.Printf("Error generating self-signed certs: %v\n", err)
logger.Warn("Error generating self-signed certs", zap.Error(err))
} else {
logger.Info("Successfully generated self-signed certificates.")
fmt.Println("Certificates generated successfully.")
}
}

func runGenerateConfig(config *viper.Viper, logger *zap.Logger) {
configPkg.CreateDefaultConfig(config, logger)
logger.Info("Default configuration file created.")
fmt.Println("Configuration file generated successfully.")
}

func runGenerateAdmin(db *db.Database, logger *zap.Logger) {
adminPw, err := password.Generate(64, 10, 10, false, false)
if err != nil {
logger.Fatal("Error generating admin password", zap.Error(err))
}

// Hash the password for security
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(adminPw), bcrypt.DefaultCost)
if err != nil {
logger.Fatal("Error hashing admin password", zap.Error(err))
}

// Admin data
temporalAdmin := structs.User{
UserID: uuid.New(),
Username: "admin",
Password: string(hashedPassword),
Groups: []string{"Admin", "StorageAdmin", "Audit"},
CreationTime: time.Now(),
UpdateTime: time.Now(),
ApiKeys: nil,
}

// Insert admin
adminInsertionData, err := db.DB.Create("user", temporalAdmin)
if err != nil {
logger.Fatal("Error inserting default admin into DB", zap.Error(err))
}

// Unmarshal data
var createdUser structs.User
err = surrealdb.Unmarshal(adminInsertionData, &createdUser)
if err != nil {
logger.Fatal("Error querying default admin", zap.Error(err))
}

pp.Println("Admin Username:", createdUser.Username)
pp.Println("Admin Password:", adminPw) // Display the original password

logger.Info("Admin user created successfully.")
}
Loading

0 comments on commit 18456f8

Please sign in to comment.