github.com/zntrio/harp/v2@v2.0.9/pkg/tasks/container/unseal.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package container
    19  
    20  import (
    21  	"context"
    22  	"encoding/base64"
    23  	"errors"
    24  	"fmt"
    25  
    26  	"github.com/awnumar/memguard"
    27  
    28  	"github.com/zntrio/harp/v2/pkg/container"
    29  	"github.com/zntrio/harp/v2/pkg/sdk/types"
    30  	"github.com/zntrio/harp/v2/pkg/tasks"
    31  )
    32  
    33  // UnsealTask implements secret container unsealing task.
    34  type UnsealTask struct {
    35  	ContainerReader tasks.ReaderProvider
    36  	OutputWriter    tasks.WriterProvider
    37  	ContainerKey    *memguard.LockedBuffer
    38  	PreSharedKey    *memguard.LockedBuffer
    39  }
    40  
    41  // Run the task.
    42  func (t *UnsealTask) Run(ctx context.Context) error {
    43  	// Check arguments
    44  	if types.IsNil(t.ContainerReader) {
    45  		return errors.New("unable to run task with a nil containerReader provider")
    46  	}
    47  	if types.IsNil(t.OutputWriter) {
    48  		return errors.New("unable to run task with a nil outputWriter provider")
    49  	}
    50  	if t.ContainerKey == nil {
    51  		return errors.New("unable to run task with a nil container key")
    52  	}
    53  
    54  	// Create input reader
    55  	reader, err := t.ContainerReader(ctx)
    56  	if err != nil {
    57  		return fmt.Errorf("unable to open input bundle reader: %w", err)
    58  	}
    59  
    60  	// Load input container
    61  	in, err := container.Load(reader)
    62  	if err != nil {
    63  		return fmt.Errorf("unable to read input container: %w", err)
    64  	}
    65  
    66  	// Seal options
    67  	sopts := []container.Option{}
    68  
    69  	// Process pre-shared key
    70  	if t.PreSharedKey != nil {
    71  		// Try to decode preshared key
    72  		psk, errDecode := base64.RawURLEncoding.DecodeString(t.PreSharedKey.String())
    73  		if errDecode != nil {
    74  			return fmt.Errorf("unable to decode pre-shared key: %w", errDecode)
    75  		}
    76  		sopts = append(sopts, container.WithPreSharedKey(memguard.NewBufferFromBytes(psk)))
    77  		t.PreSharedKey.Destroy()
    78  	}
    79  
    80  	// Unseal the container
    81  	out, err := container.Unseal(in, t.ContainerKey, sopts...)
    82  	if err != nil {
    83  		return fmt.Errorf("unable to unseal bundle content: %w", err)
    84  	}
    85  
    86  	// Create output writer
    87  	writer, err := t.OutputWriter(ctx)
    88  	if err != nil {
    89  		return fmt.Errorf("unable to open output bundle: %w", err)
    90  	}
    91  
    92  	// Dump all content
    93  	if err := container.Dump(writer, out); err != nil {
    94  		return fmt.Errorf("unable to write unsealed container: %w", err)
    95  	}
    96  
    97  	// No error
    98  	return nil
    99  }