mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-18 06:21:35 -06:00
afb30d3f9d
Brace yourselves! For there are many touched files here. No changes in semantics however. Spent a long time trying out the various optional rules gocritic provides, and settled for a few of them. There are more I really like, but that would take many hours to address across the codebase. Perhaps others find gocritic too pedantic? If so, we can merge the fixes without enabling the rule. Signed-off-by: Anders Eknert <anders@styra.com>
148 lines
4.4 KiB
Go
148 lines
4.4 KiB
Go
// Copyright 2020 The OPA Authors. All rights reserved.
|
|
// Use of this source code is governed by an Apache2
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package bundle
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/open-policy-agent/opa/v1/ast"
|
|
"github.com/open-policy-agent/opa/v1/bundle"
|
|
"github.com/open-policy-agent/opa/v1/resolver/wasm"
|
|
"github.com/open-policy-agent/opa/v1/storage"
|
|
)
|
|
|
|
// LoadWasmResolversFromStore will lookup all Wasm modules from the store along with the
|
|
// associated bundle manifest configuration and instantiate the respective resolvers.
|
|
func LoadWasmResolversFromStore(ctx context.Context, store storage.Store, txn storage.Transaction, otherBundles map[string]*bundle.Bundle) ([]*wasm.Resolver, error) {
|
|
bundleNames, err := bundle.ReadBundleNamesFromStore(ctx, store, txn)
|
|
if err != nil && !storage.IsNotFound(err) {
|
|
return nil, err
|
|
}
|
|
|
|
var resolversToLoad []*bundle.WasmModuleFile
|
|
for _, bundleName := range bundleNames {
|
|
var wasmResolverConfigs []bundle.WasmResolver
|
|
rawModules := map[string][]byte{}
|
|
|
|
// Save round-tripping the bundle that was just activated
|
|
if _, ok := otherBundles[bundleName]; ok {
|
|
wasmResolverConfigs = otherBundles[bundleName].Manifest.WasmResolvers
|
|
for _, wmf := range otherBundles[bundleName].WasmModules {
|
|
rawModules[wmf.Path] = wmf.Raw
|
|
}
|
|
} else {
|
|
wasmResolverConfigs, err = bundle.ReadWasmMetadataFromStore(ctx, store, txn, bundleName)
|
|
if err != nil && !storage.IsNotFound(err) {
|
|
return nil, fmt.Errorf("failed to read wasm module manifest from store: %s", err)
|
|
}
|
|
rawModules, err = bundle.ReadWasmModulesFromStore(ctx, store, txn, bundleName)
|
|
if err != nil && !storage.IsNotFound(err) {
|
|
return nil, fmt.Errorf("failed to read wasm modules from store: %s", err)
|
|
}
|
|
}
|
|
|
|
for path, raw := range rawModules {
|
|
wmf := &bundle.WasmModuleFile{
|
|
URL: path,
|
|
Path: path,
|
|
Raw: raw,
|
|
}
|
|
for _, resolverConf := range wasmResolverConfigs {
|
|
if resolverConf.Module == path {
|
|
ref, err := ast.PtrRef(ast.DefaultRootDocument, resolverConf.Entrypoint)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse wasm module entrypoint '%s': %s", resolverConf.Entrypoint, err)
|
|
}
|
|
wmf.Entrypoints = append(wmf.Entrypoints, ref)
|
|
}
|
|
}
|
|
if len(wmf.Entrypoints) > 0 {
|
|
resolversToLoad = append(resolversToLoad, wmf)
|
|
}
|
|
}
|
|
}
|
|
|
|
var resolvers []*wasm.Resolver
|
|
if len(resolversToLoad) > 0 {
|
|
// Get a full snapshot of the current data (including any from "outside" the bundles)
|
|
data, err := store.Read(ctx, txn, storage.Path{})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to initialize wasm runtime: %s", err)
|
|
}
|
|
|
|
for _, wmf := range resolversToLoad {
|
|
resolver, err := wasm.New(wmf.Entrypoints, wmf.Raw, data)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to initialize wasm module for entrypoints '%s': %s", wmf.Entrypoints, err)
|
|
}
|
|
resolvers = append(resolvers, resolver)
|
|
}
|
|
}
|
|
return resolvers, nil
|
|
}
|
|
|
|
// LoadBundleFromDisk loads a previously persisted activated bundle from disk
|
|
func LoadBundleFromDisk(path, name string, bvc *bundle.VerificationConfig) (*bundle.Bundle, error) {
|
|
return LoadBundleFromDiskForRegoVersion(ast.RegoV0, path, name, bvc)
|
|
}
|
|
|
|
func LoadBundleFromDiskForRegoVersion(regoVersion ast.RegoVersion, path, name string, bvc *bundle.VerificationConfig) (*bundle.Bundle, error) {
|
|
bundlePath := filepath.Join(path, name, "bundle.tar.gz")
|
|
|
|
_, err := os.Stat(bundlePath)
|
|
if err == nil {
|
|
f, err := os.Open(bundlePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
|
|
r := bundle.NewCustomReader(bundle.NewTarballLoaderWithBaseURL(f, "")).
|
|
WithRegoVersion(regoVersion)
|
|
|
|
if bvc != nil {
|
|
r = r.WithBundleVerificationConfig(bvc)
|
|
}
|
|
|
|
b, err := r.Read()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &b, nil
|
|
} else if os.IsNotExist(err) {
|
|
return nil, nil
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
// SaveBundleToDisk saves the given raw bytes representing the bundle's content to disk
|
|
func SaveBundleToDisk(path string, raw io.Reader) (string, error) {
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
err = os.MkdirAll(path, os.ModePerm)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
if raw == nil {
|
|
return "", errors.New("no raw bundle bytes to persist to disk")
|
|
}
|
|
|
|
dest, err := os.CreateTemp(path, ".bundle.tar.gz.*.tmp")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer dest.Close()
|
|
|
|
_, err = io.Copy(dest, raw)
|
|
return dest.Name(), err
|
|
}
|