templates

package
v3.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 19, 2023 License: Apache-2.0 Imports: 26 Imported by: 2

Documentation

Index

Examples

Constants

View Source
const (
	IVSize = 16 // Size in bytes

)

Variables

View Source
var (
	ErrAESKeyNotSet                      = errors.New("AESKey must be set to use this encryption mode")
	ErrInvalidAESKey                     = errors.New("the AES key is invalid")
	ErrInvalidB64OfEncrypted             = errors.New("the encrypted string is invalid base64")
	ErrIVNotSet                          = errors.New("initialization vector must be set to use this encryption mode")
	ErrInvalidIV                         = errors.New("initialization vector must be 128 bits")
	ErrInvalidPKCS7Padding               = errors.New("invalid PCKS7 padding")
	ErrMissingAPIResource                = errors.New("one or more API resources are not installed on the API server")
	ErrMissingAPIResourceInvalidTemplate = errors.New(
		"one or more API resources are not installed on the API server which could have led to the templating error",
	)
	ErrProtectNotEnabled  = errors.New("the protect template function is not enabled in this mode")
	ErrNewLinesNotAllowed = errors.New("new lines are not allowed in the string passed to the toLiteral function")
	ErrInvalidContextType = errors.New(
		"the input context must be a struct, with either string fields or map[string]string fields",
	)
)

Functions

func HasTemplate

func HasTemplate(template []byte, startDelim string, checkForEncrypted bool) bool

HasTemplate performs a simple check for the template start delimiter or the "$ocm_encrypted" prefix (checkForEncrypted must be set to true) to indicate if the input byte slice has a template. If the startDelim argument is an empty string, the default start delimiter of "{{" will be used.

func UsesEncryption

func UsesEncryption(template []byte, startDelim string, stopDelim string) bool

UsesEncryption searches for templates that would generate encrypted values and returns a boolean whether one was found.

Types

type Config

type Config struct {
	AdditionalIndentation uint
	DisabledFunctions     []string
	EncryptionConfig
	KubeAPIResourceList []*metav1.APIResourceList
	LookupNamespace     string
	StartDelim          string
	StopDelim           string
	InputIsYAML         bool
}

Config is a struct containing configuration for the API. Some are required.

- AdditionalIndentation sets the number of additional spaces to be added to the input number to the indent method. This is useful in situations when the indentation should be relative to a logical starting point in a YAML file.

- DisabledFunctions is a slice of default template function names that should be disabled. - KubeAPIResourceList sets the cache for the Kubernetes API resources. If this is set, template processing will not try to rediscover the Kubernetes API resources needed for dynamic client/ GVK lookups.

- EncryptionConfig is the configuration for template encryption/decryption functionality.

- InitializationVector is the initialization vector (IV) used in the AES-CBC encryption/decryption. Note that it must be equal to the AES block size which is always 128 bits (16 bytes). This value must be random but does not need to be private. Its purpose is to make the same plaintext value, when encrypted with the same AES key, appear unique. When performing decryption, the IV must be the same as it was for the encryption of the data. Note that all values encrypted in the template will use this same IV, which means that duplicate plaintext values that are encrypted will yield the same encrypted value in the template.

- LookupNamespace is the namespace to restrict "lookup" template functions (e.g. fromConfigMap) to. If this is not set (i.e. an empty string), then all namespaces can be used.

- StartDelim customizes the start delimiter used to distinguish a template action. This defaults to "{{". If StopDelim is set, this must also be set.

- StopDelim customizes the stop delimiter used to distinguish a template action. This defaults to "}}". If StartDelim is set, this must also be set.

- InputIsYAML can be set to true to indicate that the input to the template is already in YAML format and thus does not need to be converted from JSON to YAML before template processing occurs. This should be set to true when passing raw YAML directly to the template resolver.

type EncryptionConfig

type EncryptionConfig struct {
	AESKey                []byte
	AESKeyFallback        []byte
	DecryptionConcurrency uint8
	DecryptionEnabled     bool
	EncryptionEnabled     bool
	InitializationVector  []byte
}

EncryptionConfig is a struct containing configuration for template encryption/decryption functionality.

- AESKey is an AES key (e.g. AES-256) to use for the "protect" template function and decrypting such values.

- AESKeyFallback is an AES key to try if the decryption fails using AESKey.

- DecryptionConcurrency is the concurrency (i.e. number of Goroutines) limit when decrypting encrypted strings. Not setting this value is the equivalent of setting this to 1, which means no concurrency.

- DecryptionEnabled enables automatic decrypting of encrypted strings. AESKey and InitializationVector must also be set if this is enabled.

- EncryptionEnabled enables the "protect" template function and "fromSecret" returns encrypted content. AESKey and InitializationVector must also be set if this is enabled.

- InitializationVector is the initialization vector (IV) used in the AES-CBC encryption/decryption. Note that it must be equal to the AES block size which is always 128 bits (16 bytes). This value must be random but does not need to be private. Its purpose is to make the same plaintext value, when encrypted with the same AES key, appear unique. When performing decryption, the IV must be the same as it was for the encryption of the data. Note that all values encrypted in the template will use this same IV, which means that duplicate plaintext values that are encrypted will yield the same encrypted value in the template.

type TemplateResolver

type TemplateResolver struct {
	// contains filtered or unexported fields
}

TemplateResolver is the API for processing templates. It's better to use the NewResolver function instead of instantiating this directly so that configuration defaults and validation are applied.

func NewResolver

func NewResolver(kubeClient *kubernetes.Interface, kubeConfig *rest.Config, config Config) (*TemplateResolver, error)

NewResolver creates a new TemplateResolver instance, which is the API for processing templates.

- kubeClient is the Kubernetes client to be used for the template lookup functions.

- config is the Config instance for configuration for template processing.

func (*TemplateResolver) ResolveTemplate

func (t *TemplateResolver) ResolveTemplate(tmplRaw []byte, context interface{}) (TemplateResult, error)

ResolveTemplate accepts a map marshaled as JSON or YAML. It also accepts a struct with string fields that will be made available when the template is processed. For example, if the argument is `struct{ClusterName string}{"cluster1"}`, the value `cluster1` would be available with `{{ .ClusterName }}`. This can also be `nil` if no fields should be made available.

ResolveTemplate will process any template strings in the map and return the processed map. The ErrMissingAPIResource is returned when one or more "lookup" calls referenced an API resource which isn't installed on the Kubernetes API server. In this case, the resolved template is still returned. ErrMissingAPIResourceInvalidTemplate can also be returned in this case but it also means the template failed to resolve, so the resolved template will not be returned.

Example

nolint: nosnakecase

policyYAML := `
---
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
  name: demo-sampleapp-config
  namespace: sampleapp
spec:
  remediationAction: enforce
  namespaceSelector:
    exclude:
    - kube-*
    include:
    - default
  object-templates:
  - complianceType: musthave
    objectDefinition:
      kind: ConfigMap
      apiVersion: v1
      metadata:
        name: demo-sampleapp-config
        namespace: test
      data:
        message: '{{ "VGVtcGxhdGVzIHJvY2sh" | base64dec }}'
        b64-cluster-name: '{{ .ClusterName | base64enc }}'
    severity: high
`

policyJSON, err := yamlToJSON([]byte(policyYAML))
if err != nil {
	fmt.Fprintf(os.Stderr, "Failed to convert the policy YAML to JSON: %v\n", err)
	panic(err)
}

resolver, err := NewResolver(&k8sClient, k8sConfig, Config{})
if err != nil {
	fmt.Fprintf(os.Stderr, "Failed to instantiate the templatesResolver struct: %v\n", err)
	panic(err)
}

templateContext := struct{ ClusterName string }{ClusterName: "cluster0001"}

tmplResult, err := resolver.ResolveTemplate(policyJSON, templateContext)
policyResolvedJSON := tmplResult.ResolvedJSON

if err != nil {
	fmt.Fprintf(os.Stderr, "Failed to process the policy YAML: %v\n", err)
	panic(err)
}

var policyResolved interface{}
err = yaml.Unmarshal(policyResolvedJSON, &policyResolved)

objTmpls := policyResolved.(map[string]interface{})["spec"].(map[string]interface{})["object-templates"]
objDef := objTmpls.([]interface{})[0].(map[string]interface{})["objectDefinition"]

data, ok := objDef.(map[string]interface{})["data"].(map[string]interface{})
if !ok {
	fmt.Fprintf(os.Stderr, "Failed to process the policy YAML: %v\n", err)
	panic(err)
}

message, ok := data["message"].(string)
if !ok {
	fmt.Fprintf(os.Stderr, "Failed to process the policy YAML: %v\n", err)
	panic(err)
}

b64ClusterName, ok := data["b64-cluster-name"].(string)
if !ok {
	fmt.Fprintf(os.Stderr, "Failed to process the policy YAML: %v\n", err)
	panic(err)
}

fmt.Println(message)
fmt.Println(b64ClusterName)
Output:

Templates rock!
Y2x1c3RlcjAwMDE=

func (*TemplateResolver) SetEncryptionConfig

func (t *TemplateResolver) SetEncryptionConfig(encryptionConfig EncryptionConfig) error

SetEncryptionConfig accepts an EncryptionConfig struct and validates it to ensure that if encryption and/or decryption are enabled that the AES Key and Initialization Vector are valid. If validation passes, SetEncryptionConfig updates the EncryptionConfig in the TemplateResolver configuration. Otherwise, an error is returned and the configuration is unchanged.

func (*TemplateResolver) SetKubeAPIResourceList

func (t *TemplateResolver) SetKubeAPIResourceList(resourceList []*metav1.APIResourceList)

SetKubeAPIResourceList overrides the KubeAPIResourceList value on the TemplateResolver configuration.

type TemplateResult

type TemplateResult struct {
	ResolvedJSON      []byte
	ReferencedObjects []client.ObjectIdentifier
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL