pkg/container/identity/api.go (72 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package identity import ( "bytes" "context" "encoding/base64" "encoding/json" "errors" "fmt" "time" "github.com/elastic/harp/pkg/container/identity/key" "github.com/elastic/harp/pkg/sdk/types" "github.com/elastic/harp/pkg/sdk/value" ) // Identity object to hold container sealer identity information. type Identity struct { APIVersion string `json:"@apiVersion"` Kind string `json:"@kind"` Timestamp time.Time `json:"@timestamp"` Description string `json:"@description"` Public string `json:"public"` Private *PrivateKey `json:"private"` Signature string `json:"signature"` } // HasPrivateKey returns true if identity as a wrapped private. func (i *Identity) HasPrivateKey() bool { return i.Private != nil } // Decrypt private key with given transformer. func (i *Identity) Decrypt(ctx context.Context, t value.Transformer) (*key.JSONWebKey, error) { // Check arguments if types.IsNil(t) { return nil, fmt.Errorf("can't process with nil transformer") } if !i.HasPrivateKey() { return nil, fmt.Errorf("trying to decrypt a nil private key") } // Decode payload payload, err := base64.RawURLEncoding.DecodeString(i.Private.Content) if err != nil { return nil, fmt.Errorf("unable to decode private key: %w", err) } // Apply transformation clearText, err := t.From(ctx, payload) if err != nil { return nil, fmt.Errorf("unable to decrypt identity payload: %w", err) } // Decode key var pk key.JSONWebKey if err = json.NewDecoder(bytes.NewReader(clearText)).Decode(&pk); err != nil { return nil, fmt.Errorf("unable to decode payload as JSON: %w", err) } // Return result return &pk, nil } // Verify the identity signature using its own public key. func (i *Identity) Verify() error { // Clear the signature id := &Identity{} *id = *i // Clean protected id.Signature = "" id.Private = nil // Prepare protected protected, err := json.Marshal(id) if err != nil { return fmt.Errorf("unable to serialize identity for signature: %w", err) } // Decode the signature sig, err := base64.RawURLEncoding.DecodeString(i.Signature) if err != nil { return fmt.Errorf("unable to decode the signature: %w", err) } // Decode public key pubKey, err := key.FromString(id.Public) if err != nil { return fmt.Errorf("unable to decode public key: %w", err) } // Validate signature if pubKey.Verify(protected, sig) { return nil } return errors.New("unable to validate identity signature") } // PrivateKey wraps encoded private and related informations. type PrivateKey struct { Encoding string `json:"encoding,omitempty"` Content string `json:"content"` }