func()

in yubikey/pkg/tasks/container/identity.go [50:130]


func (t *IdentityTask) Run(ctx context.Context) error {
	// Check arguments
	if t.Description == "" {
		return fmt.Errorf("description must not be blank")
	}

	// Create identity
	id, payload, err := identity.New(rand.Reader, t.Description, key.Ed25519)
	if err != nil {
		return fmt.Errorf("unable to create new identity: %w", err)
	}

	// Get PIV Manager
	manager := piv.Manager()

	// Try to open card
	card, err := manager.Open(t.Serial, t.Slot)
	if err != nil {
		return fmt.Errorf("unable to open PIV card: %w", err)
	}
	defer func() {
		if card != nil {
			if errClose := card.Close(); errClose != nil {
				log.For(ctx).Error("unable to close card", zap.Error(errClose))
			}
		}
	}()

	// Extract public key
	cardPublicKey := card.Public()
	pivCompressed := elliptic.MarshalCompressed(cardPublicKey.Curve, cardPublicKey.X, cardPublicKey.Y)

	// Identity tag
	tag := sha256.Sum256(pivCompressed)

	// Initialize envelope service
	pivService, err := piv.Service(card, func(msg string) (string, error) {
		pin, errPin := cmdutil.ReadSecret(msg, false)
		if errPin != nil {
			return "", fmt.Errorf("unable to read pin from terminal: %w", errPin)
		}

		// No error
		return pin.String(), nil
	})
	if err != nil {
		return fmt.Errorf("unable to initialize PIV service: %w", err)
	}

	// Initialize Data encryption transformer
	transformer, err := envelope.Transformer(pivService, aead.Chacha20Poly1305)
	if err != nil {
		return fmt.Errorf("unable to initialize KMS service: %w", err)
	}

	// Apply transformation
	cipherText, err := transformer.To(ctx, payload)
	if err != nil {
		return fmt.Errorf("unable to encrypt identity payload: %w", err)
	}

	// Wrap private key
	id.Private = &identity.PrivateKey{
		Encoding: fmt.Sprintf("piv:yubikey:%d:%02x:%s", t.Serial, t.Slot, base64.RawStdEncoding.EncodeToString(tag[:4])),
		Content:  base64.RawURLEncoding.EncodeToString(cipherText),
	}

	// Retrieve output writer
	writer, err := t.OutputWriter(ctx)
	if err != nil {
		return fmt.Errorf("unable to retrieve output writer handle: %w", err)
	}

	// Create identity output
	if err := json.NewEncoder(writer).Encode(id); err != nil {
		return fmt.Errorf("unable to serialize final identity: %w", err)
	}

	// No error
	return nil
}