github.com/zntrio/harp/v2@v2.0.9/pkg/container/identity/api.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 identity
    19  
    20  import (
    21  	"bytes"
    22  	"context"
    23  	"encoding/base64"
    24  	"encoding/json"
    25  	"errors"
    26  	"fmt"
    27  	"time"
    28  
    29  	"github.com/zntrio/harp/v2/pkg/container/identity/key"
    30  	"github.com/zntrio/harp/v2/pkg/sdk/types"
    31  	"github.com/zntrio/harp/v2/pkg/sdk/value"
    32  )
    33  
    34  // Identity object to hold container sealer identity information.
    35  type Identity struct {
    36  	APIVersion  string      `json:"@apiVersion"`
    37  	Kind        string      `json:"@kind"`
    38  	Timestamp   time.Time   `json:"@timestamp"`
    39  	Description string      `json:"@description"`
    40  	Public      string      `json:"public"`
    41  	Private     *PrivateKey `json:"private"`
    42  	Signature   string      `json:"signature"`
    43  }
    44  
    45  // HasPrivateKey returns true if identity as a wrapped private.
    46  func (i *Identity) HasPrivateKey() bool {
    47  	return i.Private != nil
    48  }
    49  
    50  // Decrypt private key with given transformer.
    51  func (i *Identity) Decrypt(ctx context.Context, t value.Transformer) (*key.JSONWebKey, error) {
    52  	// Check arguments
    53  	if types.IsNil(t) {
    54  		return nil, fmt.Errorf("can't process with nil transformer")
    55  	}
    56  	if !i.HasPrivateKey() {
    57  		return nil, fmt.Errorf("trying to decrypt a nil private key")
    58  	}
    59  
    60  	// Decode payload
    61  	payload, err := base64.RawURLEncoding.DecodeString(i.Private.Content)
    62  	if err != nil {
    63  		return nil, fmt.Errorf("unable to decode private key: %w", err)
    64  	}
    65  
    66  	// Apply transformation
    67  	clearText, err := t.From(ctx, payload)
    68  	if err != nil {
    69  		return nil, fmt.Errorf("unable to decrypt identity payload: %w", err)
    70  	}
    71  
    72  	// Decode key
    73  	var pk key.JSONWebKey
    74  	if err = json.NewDecoder(bytes.NewReader(clearText)).Decode(&pk); err != nil {
    75  		return nil, fmt.Errorf("unable to decode payload as JSON: %w", err)
    76  	}
    77  
    78  	// Return result
    79  	return &pk, nil
    80  }
    81  
    82  // Verify the identity signature using its own public key.
    83  func (i *Identity) Verify() error {
    84  	// Clear the signature
    85  	id := &Identity{}
    86  	*id = *i
    87  
    88  	// Clean protected
    89  	id.Signature = ""
    90  	id.Private = nil
    91  
    92  	// Prepare protected
    93  	protected, err := json.Marshal(id)
    94  	if err != nil {
    95  		return fmt.Errorf("unable to serialize identity for signature: %w", err)
    96  	}
    97  
    98  	// Decode the signature
    99  	sig, err := base64.RawURLEncoding.DecodeString(i.Signature)
   100  	if err != nil {
   101  		return fmt.Errorf("unable to decode the signature: %w", err)
   102  	}
   103  
   104  	// Decode public key
   105  	pubKey, err := key.FromString(id.Public)
   106  	if err != nil {
   107  		return fmt.Errorf("unable to decode public key: %w", err)
   108  	}
   109  
   110  	// Validate signature
   111  	if pubKey.Verify(protected, sig) {
   112  		return nil
   113  	}
   114  
   115  	return errors.New("unable to validate identity signature")
   116  }
   117  
   118  // PrivateKey wraps encoded private and related informations.
   119  type PrivateKey struct {
   120  	Encoding string `json:"encoding,omitempty"`
   121  	Content  string `json:"content"`
   122  }