github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/cmdutil/password.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 cmdutil
    19  
    20  import (
    21  	"fmt"
    22  	"os"
    23  	"syscall"
    24  
    25  	"github.com/awnumar/memguard"
    26  
    27  	"github.com/zntrio/harp/v2/pkg/sdk/security"
    28  
    29  	"golang.org/x/term"
    30  )
    31  
    32  // ReadSecret reads password from Stdin and returns a lockedbuffer.
    33  func ReadSecret(prompt string, confirmation bool) (*memguard.LockedBuffer, error) {
    34  	var (
    35  		err             error
    36  		password        []byte
    37  		passwordConfirm []byte
    38  	)
    39  	defer memguard.WipeBytes(password)
    40  	defer memguard.WipeBytes(passwordConfirm)
    41  
    42  	// Ask to password
    43  	fmt.Fprintf(os.Stdout, "%s: ", prompt)
    44  	//nolint:unconvert // stdin doesn't share same type on each platform
    45  	password, err = term.ReadPassword(int(syscall.Stdin))
    46  	if err != nil {
    47  		return nil, fmt.Errorf("unable to read secret")
    48  	}
    49  
    50  	fmt.Fprint(os.Stdout, "\n")
    51  
    52  	// Check if confirmation is requested
    53  	if !confirmation {
    54  		// Return locked buffer
    55  		return memguard.NewBufferFromBytes(password), nil
    56  	}
    57  
    58  	fmt.Fprintf(os.Stdout, "%s (confirmation): ", prompt)
    59  	//nolint:unconvert // stdin doesn't share same type on each platform
    60  	passwordConfirm, err = term.ReadPassword(int(syscall.Stdin))
    61  	if err != nil {
    62  		return nil, fmt.Errorf("unable to read secret confirmation")
    63  	}
    64  
    65  	fmt.Fprint(os.Stdout, "\n")
    66  
    67  	// Compare if equal
    68  	if !security.SecureCompare(password, passwordConfirm) {
    69  		return nil, fmt.Errorf("passphrase doesn't match")
    70  	}
    71  
    72  	// Return locked buffer
    73  	return memguard.NewBufferFromBytes(password), nil
    74  }