Skip to content

Commit 70bcb25

Browse files
FriedJannikaaronzi
andauthored
Update to Metamodel Version 3.2 (#327)
* Updates Go Version and adapts SNAPSHOT Workflow (#8) * Update to latest aas-package3-golang * Fixes go mod * Adapts Vuln Scan Workflow * Updates SUPPLY_CHAIN_SECURITY.md * Update to 3.2 dependencies Co-authored-by: Aaron Zielstorff <aaron.zielstorff@iese.fraunhofer.de> * Adapts Submodel Repository OpenAPI Yaml to Version 3.2 (incl. SSP 005, 006, 007) * 1_1_0 Schema Update * Updates remaining openapi.yml files Co-authored-by: Jannik Fried <Jannik.Fried@iese.fraunhofer.de> * Adds aaset kind migration * Adds small fixes to openapi files * Fixes aas env test failures * Implements v3.2 API capabilities * Increases test coverage and adds docu * Fixes schema patch test * Implement history and audit configuration with eventing support - Added history configuration options via environment variables, including modes for history behavior (off, api, audit), retention days, immutability settings, and audit identity modes. - Introduced ChangeEvent structure to encapsulate event data for history storage. - Updated AppendVersionTx to append immutable event rows instead of updating existing history rows. - Implemented SHA-256 hashing for canonical JSON snapshots and row hashes for history events. - Added support for audit metadata in history events, including actor subject, request ID, and other contextual information. - Created tests for history functionality, ensuring stable hashing and correct behavior under different configurations. - Enhanced documentation to reflect new history features and configuration options. * Implement PostgreSQL mutation guards for history tables and update related services * Fixes failing tests * Rem test * 1_1_1 Changes - changes openapi - adds history guard * Fixes typo * Improves new schema changes Co-authored-by: Jannik Fried <Jannik.Fried@iese.fraunhofer.de> * Small fixes * Fixes linting errors * Resolves Review Remark * Adapts .gitignore * Adds missing endpoints * Small Changes * Improves documentation * Adresses review remarks * Adresses further review remarks * Adds missing method in pkg submodel repo api * Adresses review remarks * Fixes swagger base path handling * Fixes incorrect operation contracts * Adresses Martins Remarks * Fixes incorrect submodel repo query test setup * Adds logging for new configs and changes order from new to old * Prepares the new history storage diff mode --------- Co-authored-by: Aaron Zielstorff <aaron.zielstorff@iese.fraunhofer.de>
1 parent d9c0e2c commit 70bcb25

111 files changed

Lines changed: 16293 additions & 8421 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,9 @@ debug.test.*
4747
.gocache/
4848
logs/
4949

50-
.kilo/
50+
.kilo/
51+
52+
# Generated by AAS environment serialization integration tests
53+
internal/aasenvironment/integration_tests/testdata_results/
54+
55+
.cache/

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ See [structure.md](docu/developer/structure.md) and related files for details on
200200
- Example endpoint: `/submodels/{id}/submodel-elements/{idShort}/attachment`
201201
- AAS environment import endpoint: `/upload` (multipart/form-data with file part `file`)
202202
- Supported upload media types: `application/aasx+xml`, `application/aasx+json`, `application/asset-administration-shell+xml`, `application/asset-administration-shell+json`, `application/json`, `application/xml`, `text/xml`
203+
- AAS v3.2 history and recent changes: [user guide](docu/user/aas_api_v3_2.md) and [runtime notes](docu/developer/aas_v3_2_runtime.md)
203204
- See [structure_cmd.md](docu/developer/structure_cmd.md) for details
204205

205206
## 9. Contribution Guidelines

cmd/aasenvironmentservice/main.go

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ package main
2929
import (
3030
"context"
3131
"crypto/rsa"
32+
"database/sql"
3233
"embed"
3334
"flag"
3435
"fmt"
@@ -44,6 +45,7 @@ import (
4445
aasrepositorydb "github.com/eclipse-basyx/basyx-go-components/internal/aasrepository/persistence"
4546
"github.com/eclipse-basyx/basyx-go-components/internal/common"
4647
"github.com/eclipse-basyx/basyx-go-components/internal/common/asyncbulk"
48+
"github.com/eclipse-basyx/basyx-go-components/internal/common/history"
4749
"github.com/eclipse-basyx/basyx-go-components/internal/common/jws"
4850
commonmodel "github.com/eclipse-basyx/basyx-go-components/internal/common/model"
4951
auth "github.com/eclipse-basyx/basyx-go-components/internal/common/security"
@@ -79,6 +81,13 @@ func runServer(ctx context.Context, configPath string) error {
7981
if err := commonmodel.SetVerificationMode(cfg.Server.StrictVerification); err != nil {
8082
return err
8183
}
84+
history.Configure(history.Config{
85+
Mode: cfg.History.Mode,
86+
RetentionDays: cfg.History.RetentionDays,
87+
FullSnapshotInterval: cfg.History.FullSnapshotInterval,
88+
Immutability: cfg.History.Immutability,
89+
AuditIdentityMode: cfg.History.AuditIdentityMode,
90+
})
8291

8392
registrySyncConfig, err := aasenvironment.NewRegistrySyncConfig(
8493
cfg.General.AASRegistryIntegration,
@@ -118,16 +127,10 @@ func runServer(ctx context.Context, configPath string) error {
118127
return err
119128
}
120129

121-
sharedDB, err := common.NewDatabaseConnection(dsn)
130+
sharedDB, err := openSharedDatabase(ctx, cfg, dsn)
122131
if err != nil {
123132
return err
124133
}
125-
if cfg.Postgres.MaxOpenConnections > 0 {
126-
sharedDB.SetMaxOpenConns(cfg.Postgres.MaxOpenConnections)
127-
}
128-
if cfg.Postgres.MaxIdleConnections > 0 {
129-
sharedDB.SetMaxIdleConns(cfg.Postgres.MaxIdleConnections)
130-
}
131134

132135
var privateKey *rsa.PrivateKey
133136
if cfg.JWS.PrivateKeyPath != "" {
@@ -149,6 +152,7 @@ func runServer(ctx context.Context, configPath string) error {
149152
if err != nil {
150153
return err
151154
}
155+
aasRepositoryPersistence.SetJWSPrivateKey(privateKey)
152156
submodelRepositoryPersistence, err := submodelrepositorydb.NewSubmodelDatabaseFromDB(sharedDB, privateKey, cfg.Server.StrictVerification)
153157
if err != nil {
154158
return err
@@ -220,35 +224,51 @@ func runServer(ctx context.Context, configPath string) error {
220224
if err = auth.SetupSecurity(ctx, cfg, apiRouter); err != nil {
221225
return err
222226
}
227+
versioningGuard := history.NewMutationCoverageGuard(apiRouter)
228+
apiRouter.Use(versioningGuard.Middleware)
223229

224-
for _, rt := range aasRegistryCtrl.Routes() {
230+
for operation, rt := range aasRegistryCtrl.Routes() {
231+
versioningGuard.ClassifyRoute(operation, rt.Method, rt.Pattern)
225232
apiRouter.Method(rt.Method, rt.Pattern, rt.HandlerFunc)
226233
}
227-
for _, rt := range smRegistryCtrl.Routes() {
234+
for operation, rt := range smRegistryCtrl.Routes() {
235+
versioningGuard.ClassifyRoute(operation, rt.Method, rt.Pattern)
228236
apiRouter.Method(rt.Method, rt.Pattern, rt.HandlerFunc)
229237
}
230-
for _, rt := range aasRepositoryCtrl.Routes() {
238+
for operation, rt := range aasRepositoryCtrl.Routes() {
239+
versioningGuard.ClassifyRoute(operation, rt.Method, rt.Pattern)
231240
apiRouter.Method(rt.Method, rt.Pattern, rt.HandlerFunc)
232241
}
233-
for _, rt := range smRepositoryCtrl.Routes() {
242+
for operation, rt := range smRepositoryCtrl.Routes() {
243+
versioningGuard.ClassifyRoute(operation, rt.Method, rt.Pattern)
234244
apiRouter.Method(rt.Method, rt.Pattern, rt.HandlerFunc)
235245
}
236-
for _, rt := range cdrCtrl.Routes() {
246+
for operation, rt := range cdrCtrl.Routes() {
247+
versioningGuard.ClassifyRoute(operation, rt.Method, rt.Pattern)
237248
apiRouter.Method(rt.Method, rt.Pattern, rt.HandlerFunc)
238249
}
239-
for _, rt := range discoveryCtrl.Routes() {
250+
for operation, rt := range discoveryCtrl.Routes() {
251+
versioningGuard.ClassifyRoute(operation, rt.Method, rt.Pattern)
240252
apiRouter.Method(rt.Method, rt.Pattern, rt.HandlerFunc)
241253
}
242-
for _, rt := range descriptionCtrl.Routes() {
254+
for operation, rt := range descriptionCtrl.Routes() {
255+
versioningGuard.ClassifyRoute(operation, rt.Method, rt.Pattern)
243256
apiRouter.Method(rt.Method, rt.Pattern, rt.HandlerFunc)
244257
}
258+
versioningGuard.Cover(http.MethodPost, "/bulk/shell-descriptors")
259+
versioningGuard.Cover(http.MethodPut, "/bulk/shell-descriptors")
260+
versioningGuard.Cover(http.MethodDelete, "/bulk/shell-descriptors")
261+
versioningGuard.Exempt(http.MethodPost, "/bulk/submodel-descriptors")
262+
versioningGuard.Exempt(http.MethodPut, "/bulk/submodel-descriptors")
263+
versioningGuard.Exempt(http.MethodDelete, "/bulk/submodel-descriptors")
245264
aasBulkHandler.RegisterRoutes(apiRouter, true)
246265
smBulkHandler.RegisterRoutes(apiRouter, false)
247266

248267
r.Mount(base, apiRouter)
249268

250269
// Register /upload endpoint
251270
uploadService := aasenvironment.NewUploadAPIService(persistence, customAASRepository, customSMRepository)
271+
versioningGuard.Cover(http.MethodPost, "/upload")
252272
aasenvironment.RegisterUploadAPI(apiRouter, uploadService, cfg.General.UploadMaxSizeBytes)
253273
aasenvironment.RegisterSerializationAPI(apiRouter, serializationService)
254274

@@ -291,6 +311,30 @@ func runServer(ctx context.Context, configPath string) error {
291311
return nil
292312
}
293313

314+
func openSharedDatabase(ctx context.Context, cfg *common.Config, dsn string) (*sql.DB, error) {
315+
db, err := common.NewDatabaseConnection(dsn)
316+
if err != nil {
317+
return nil, err
318+
}
319+
configurePostgresPool(db, cfg.Postgres)
320+
if err = history.ApplyPostgresGuardConfig(ctx, db); err != nil {
321+
return nil, err
322+
}
323+
return db, nil
324+
}
325+
326+
func configurePostgresPool(db *sql.DB, cfg common.PostgresConfig) {
327+
if cfg.MaxOpenConnections > 0 {
328+
db.SetMaxOpenConns(cfg.MaxOpenConnections)
329+
}
330+
if cfg.MaxIdleConnections > 0 {
331+
db.SetMaxIdleConns(cfg.MaxIdleConnections)
332+
}
333+
if cfg.ConnMaxLifetimeMinutes > 0 {
334+
db.SetConnMaxLifetime(time.Duration(cfg.ConnMaxLifetimeMinutes) * time.Minute)
335+
}
336+
}
337+
294338
func main() {
295339
ctx := context.TODO()
296340
configPath := ""

0 commit comments

Comments
 (0)