From 573f78e1b4250c0588611f70b788c8f0d3deef2b Mon Sep 17 00:00:00 2001
From: Casey Lee <cplee@nektos.com>
Date: Mon, 17 Feb 2020 21:51:49 -0800
Subject: [PATCH] support for secrets

Signed-off-by: Casey Lee <cplee@nektos.com>
---
 README.md                                     |  10 +-
 cmd/input.go                                  |   1 +
 cmd/root.go                                   |   4 +-
 cmd/secrets.go                                |  36 ++
 go.mod                                        |   1 +
 go.sum                                        |   2 +
 pkg/runner/expression.go                      |   3 +-
 pkg/runner/runner.go                          |  13 +-
 pkg/runner/testdata/secrets/push.yml          |   9 +
 vendor/github.com/howeyc/gopass/.travis.yml   |  11 +
 vendor/github.com/howeyc/gopass/LICENSE.txt   |  15 +
 .../howeyc/gopass/OPENSOLARIS.LICENSE         | 384 ++++++++++++++++++
 vendor/github.com/howeyc/gopass/README.md     |   3 +
 vendor/github.com/howeyc/gopass/pass.go       | 126 ++++++
 vendor/github.com/howeyc/gopass/terminal.go   |  41 ++
 .../howeyc/gopass/terminal_solaris.go         |  69 ++++
 vendor/modules.txt                            |   2 +
 17 files changed, 714 insertions(+), 16 deletions(-)
 create mode 100644 cmd/secrets.go
 create mode 100644 pkg/runner/testdata/secrets/push.yml
 create mode 100644 vendor/github.com/howeyc/gopass/.travis.yml
 create mode 100644 vendor/github.com/howeyc/gopass/LICENSE.txt
 create mode 100644 vendor/github.com/howeyc/gopass/OPENSOLARIS.LICENSE
 create mode 100644 vendor/github.com/howeyc/gopass/README.md
 create mode 100644 vendor/github.com/howeyc/gopass/pass.go
 create mode 100644 vendor/github.com/howeyc/gopass/terminal.go
 create mode 100644 vendor/github.com/howeyc/gopass/terminal_solaris.go

diff --git a/README.md b/README.md
index 58179fa..2235754 100644
--- a/README.md
+++ b/README.md
@@ -56,14 +56,10 @@ act -v
 
 # Secrets
 
-To run `act` with secrets, you can enter them interactively or supply them as environment variables.
-If you have a secret called `FOO` in your workflow, `act` will take whatever you have set as `FOO` in the session from which you are running `act`.
-If `FOO` is unset, it will ask you interactively.
+To run `act` with secrets, you can enter them interactively or supply them as environment variables. The following options are available for providing secrets:
 
-You can set environment variables for the current session by running `export FOO="zap"`, or globally in your `.profile`.
-You can also set environment variables *per directory* using a tool such as [direnv](https://direnv.net/).
-**Be careful not to expose secrets**:
-You may want to `.gitignore` any files or folders containing secrets, and/or encrypt secrets.
+* `act -s MY_SECRET=somevalue` - use `somevalue` as the value for `MY_SECRET`. 
+* `act -s MY_SECRET` - check for an environment variable named `MY_SECRET` and use it if it exists.  If environment variable is not defined, prompt the user for a value.
 
 # Support
 
diff --git a/cmd/input.go b/cmd/input.go
index a2adcf7..22b9afa 100644
--- a/cmd/input.go
+++ b/cmd/input.go
@@ -11,6 +11,7 @@ type Input struct {
 	workflowsPath   string
 	eventPath       string
 	reuseContainers bool
+	secrets         []string
 	dryrun          bool
 	forcePull       bool
 	logOutput       bool
diff --git a/cmd/root.go b/cmd/root.go
index 4b05c79..cf1d2f7 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -30,9 +30,10 @@ func Execute(ctx context.Context, version string) {
 	rootCmd.Flags().BoolP("watch", "w", false, "watch the contents of the local repo and run when files change")
 	rootCmd.Flags().BoolP("list", "l", false, "list workflows")
 	rootCmd.Flags().StringP("job", "j", "", "run job")
+	rootCmd.Flags().StringArrayVarP(&input.secrets, "secret", "s", []string{}, "secret to make available to actions with optional value (e.g. -s mysecret=foo or -s mysecret)")
 	rootCmd.Flags().BoolVarP(&input.reuseContainers, "reuse", "r", false, "reuse action containers to maintain state")
 	rootCmd.Flags().BoolVarP(&input.forcePull, "pull", "p", false, "pull docker image(s) if already present")
-	rootCmd.Flags().StringVarP(&input.eventPath, "event", "e", "", "path to event JSON file")
+	rootCmd.Flags().StringVarP(&input.eventPath, "eventpath", "e", "", "path to event JSON file")
 	rootCmd.PersistentFlags().StringVarP(&input.workflowsPath, "workflows", "W", "./.github/workflows/", "path to workflow files")
 	rootCmd.PersistentFlags().StringVarP(&input.workdir, "directory", "C", ".", "working directory")
 	rootCmd.PersistentFlags().BoolP("verbose", "v", false, "verbose output")
@@ -96,6 +97,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
 			ReuseContainers: input.reuseContainers,
 			Workdir:         input.Workdir(),
 			LogOutput:       input.logOutput,
+			Secrets:         newSecrets(input.secrets),
 		}
 		runner, err := runner.New(config)
 		if err != nil {
diff --git a/cmd/secrets.go b/cmd/secrets.go
new file mode 100644
index 0000000..e74f596
--- /dev/null
+++ b/cmd/secrets.go
@@ -0,0 +1,36 @@
+package cmd
+
+import (
+	"fmt"
+	"log"
+	"os"
+	"strings"
+
+	"github.com/howeyc/gopass"
+)
+
+type secrets map[string]string
+
+func newSecrets(secretList []string) secrets {
+	s := make(map[string]string)
+	for _, secretPair := range secretList {
+		secretPairParts := strings.Split(secretPair, "=")
+		if len(secretPairParts) == 2 {
+			s[secretPairParts[0]] = secretPairParts[1]
+		} else if env, ok := os.LookupEnv(secretPairParts[0]); ok && env != "" {
+			s[secretPairParts[0]] = env
+		} else {
+			fmt.Printf("Provide value for '%s': ", secretPairParts[0])
+			val, err := gopass.GetPasswdMasked()
+			if err != nil {
+				log.Fatal("abort")
+			}
+			s[secretPairParts[0]] = string(val)
+		}
+	}
+	return s
+}
+
+func (s secrets) AsMap() map[string]string {
+	return s
+}
diff --git a/go.mod b/go.mod
index cd27f57..d21486e 100644
--- a/go.mod
+++ b/go.mod
@@ -16,6 +16,7 @@ require (
 	github.com/gogo/protobuf v1.2.0 // indirect
 	github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
 	github.com/gorilla/mux v1.7.0 // indirect
+	github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c
 	github.com/inconshreveable/mousetrap v1.0.0 // indirect
 	github.com/jtolds/gls v4.2.1+incompatible // indirect
 	github.com/mgutz/str v1.2.0 // indirect
diff --git a/go.sum b/go.sum
index a33ce9d..c747a1d 100644
--- a/go.sum
+++ b/go.sum
@@ -51,6 +51,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1
 github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
 github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c h1:aY2hhxLhjEAbfXOx2nRJxCXezC6CO2V/yN+OCr1srtk=
+github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
 github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
diff --git a/pkg/runner/expression.go b/pkg/runner/expression.go
index e9ffb3d..9226faf 100644
--- a/pkg/runner/expression.go
+++ b/pkg/runner/expression.go
@@ -272,9 +272,8 @@ func (rc *RunContext) vmRunner() func(*otto.Otto) {
 }
 
 func (rc *RunContext) vmSecrets() func(*otto.Otto) {
-	secrets := make(map[string]string)
 	return func(vm *otto.Otto) {
-		_ = vm.Set("secrets", secrets)
+		_ = vm.Set("secrets", rc.Config.Secrets)
 	}
 }
 
diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go
index dc774d4..2fc21ec 100644
--- a/pkg/runner/runner.go
+++ b/pkg/runner/runner.go
@@ -18,12 +18,13 @@ type Runner interface {
 
 // Config contains the config for a new runner
 type Config struct {
-	Workdir         string // path to working directory
-	EventName       string // name of event to run
-	EventPath       string // path to JSON file to use for event.json in containers
-	ReuseContainers bool   // reuse containers to maintain state
-	ForcePull       bool   // force pulling of the image, if already present
-	LogOutput       bool   // log the output from docker run
+	Workdir         string            // path to working directory
+	EventName       string            // name of event to run
+	EventPath       string            // path to JSON file to use for event.json in containers
+	ReuseContainers bool              // reuse containers to maintain state
+	ForcePull       bool              // force pulling of the image, if already present
+	LogOutput       bool              // log the output from docker run
+	Secrets         map[string]string // list of secrets
 }
 
 type runnerImpl struct {
diff --git a/pkg/runner/testdata/secrets/push.yml b/pkg/runner/testdata/secrets/push.yml
new file mode 100644
index 0000000..a3a788e
--- /dev/null
+++ b/pkg/runner/testdata/secrets/push.yml
@@ -0,0 +1,9 @@
+name: basic
+on: push
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+      - run: |
+          echo '${{secrets.MY_SECRET}}' | grep 'top-secret'
diff --git a/vendor/github.com/howeyc/gopass/.travis.yml b/vendor/github.com/howeyc/gopass/.travis.yml
new file mode 100644
index 0000000..cc5d509
--- /dev/null
+++ b/vendor/github.com/howeyc/gopass/.travis.yml
@@ -0,0 +1,11 @@
+language: go
+
+os:
+  - linux
+  - osx
+
+go:
+  - 1.3
+  - 1.4
+  - 1.5
+  - tip
diff --git a/vendor/github.com/howeyc/gopass/LICENSE.txt b/vendor/github.com/howeyc/gopass/LICENSE.txt
new file mode 100644
index 0000000..14f7470
--- /dev/null
+++ b/vendor/github.com/howeyc/gopass/LICENSE.txt
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2012 Chris Howey
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/vendor/github.com/howeyc/gopass/OPENSOLARIS.LICENSE b/vendor/github.com/howeyc/gopass/OPENSOLARIS.LICENSE
new file mode 100644
index 0000000..da23621
--- /dev/null
+++ b/vendor/github.com/howeyc/gopass/OPENSOLARIS.LICENSE
@@ -0,0 +1,384 @@
+Unless otherwise noted, all files in this distribution are released
+under the Common Development and Distribution License (CDDL).
+Exceptions are noted within the associated source files.
+
+--------------------------------------------------------------------
+
+
+COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0
+
+1. Definitions.
+
+    1.1. "Contributor" means each individual or entity that creates
+         or contributes to the creation of Modifications.
+
+    1.2. "Contributor Version" means the combination of the Original
+         Software, prior Modifications used by a Contributor (if any),
+         and the Modifications made by that particular Contributor.
+
+    1.3. "Covered Software" means (a) the Original Software, or (b)
+         Modifications, or (c) the combination of files containing
+         Original Software with files containing Modifications, in
+         each case including portions thereof.
+
+    1.4. "Executable" means the Covered Software in any form other
+         than Source Code.
+
+    1.5. "Initial Developer" means the individual or entity that first
+         makes Original Software available under this License.
+
+    1.6. "Larger Work" means a work which combines Covered Software or
+         portions thereof with code not governed by the terms of this
+         License.
+
+    1.7. "License" means this document.
+
+    1.8. "Licensable" means having the right to grant, to the maximum
+         extent possible, whether at the time of the initial grant or
+         subsequently acquired, any and all of the rights conveyed
+         herein.
+
+    1.9. "Modifications" means the Source Code and Executable form of
+         any of the following:
+
+        A. Any file that results from an addition to, deletion from or
+           modification of the contents of a file containing Original
+           Software or previous Modifications;
+
+        B. Any new file that contains any part of the Original
+           Software or previous Modifications; or
+
+        C. Any new file that is contributed or otherwise made
+           available under the terms of this License.
+
+    1.10. "Original Software" means the Source Code and Executable
+          form of computer software code that is originally released
+          under this License.
+
+    1.11. "Patent Claims" means any patent claim(s), now owned or
+          hereafter acquired, including without limitation, method,
+          process, and apparatus claims, in any patent Licensable by
+          grantor.
+
+    1.12. "Source Code" means (a) the common form of computer software
+          code in which modifications are made and (b) associated
+          documentation included in or with such code.
+
+    1.13. "You" (or "Your") means an individual or a legal entity
+          exercising rights under, and complying with all of the terms
+          of, this License.  For legal entities, "You" includes any
+          entity which controls, is controlled by, or is under common
+          control with You.  For purposes of this definition,
+          "control" means (a) the power, direct or indirect, to cause
+          the direction or management of such entity, whether by
+          contract or otherwise, or (b) ownership of more than fifty
+          percent (50%) of the outstanding shares or beneficial
+          ownership of such entity.
+
+2. License Grants.
+
+    2.1. The Initial Developer Grant.
+
+    Conditioned upon Your compliance with Section 3.1 below and
+    subject to third party intellectual property claims, the Initial
+    Developer hereby grants You a world-wide, royalty-free,
+    non-exclusive license:
+
+        (a) under intellectual property rights (other than patent or
+            trademark) Licensable by Initial Developer, to use,
+            reproduce, modify, display, perform, sublicense and
+            distribute the Original Software (or portions thereof),
+            with or without Modifications, and/or as part of a Larger
+            Work; and
+
+        (b) under Patent Claims infringed by the making, using or
+            selling of Original Software, to make, have made, use,
+            practice, sell, and offer for sale, and/or otherwise
+            dispose of the Original Software (or portions thereof).
+
+        (c) The licenses granted in Sections 2.1(a) and (b) are
+            effective on the date Initial Developer first distributes
+            or otherwise makes the Original Software available to a
+            third party under the terms of this License.
+
+        (d) Notwithstanding Section 2.1(b) above, no patent license is
+            granted: (1) for code that You delete from the Original
+            Software, or (2) for infringements caused by: (i) the
+            modification of the Original Software, or (ii) the
+            combination of the Original Software with other software
+            or devices.
+
+    2.2. Contributor Grant.
+
+    Conditioned upon Your compliance with Section 3.1 below and
+    subject to third party intellectual property claims, each
+    Contributor hereby grants You a world-wide, royalty-free,
+    non-exclusive license:
+
+        (a) under intellectual property rights (other than patent or
+            trademark) Licensable by Contributor to use, reproduce,
+            modify, display, perform, sublicense and distribute the
+            Modifications created by such Contributor (or portions
+            thereof), either on an unmodified basis, with other
+            Modifications, as Covered Software and/or as part of a
+            Larger Work; and
+
+        (b) under Patent Claims infringed by the making, using, or
+            selling of Modifications made by that Contributor either
+            alone and/or in combination with its Contributor Version
+            (or portions of such combination), to make, use, sell,
+            offer for sale, have made, and/or otherwise dispose of:
+            (1) Modifications made by that Contributor (or portions
+            thereof); and (2) the combination of Modifications made by
+            that Contributor with its Contributor Version (or portions
+            of such combination).
+
+        (c) The licenses granted in Sections 2.2(a) and 2.2(b) are
+            effective on the date Contributor first distributes or
+            otherwise makes the Modifications available to a third
+            party.
+
+        (d) Notwithstanding Section 2.2(b) above, no patent license is
+            granted: (1) for any code that Contributor has deleted
+            from the Contributor Version; (2) for infringements caused
+            by: (i) third party modifications of Contributor Version,
+            or (ii) the combination of Modifications made by that
+            Contributor with other software (except as part of the
+            Contributor Version) or other devices; or (3) under Patent
+            Claims infringed by Covered Software in the absence of
+            Modifications made by that Contributor.
+
+3. Distribution Obligations.
+
+    3.1. Availability of Source Code.
+
+    Any Covered Software that You distribute or otherwise make
+    available in Executable form must also be made available in Source
+    Code form and that Source Code form must be distributed only under
+    the terms of this License.  You must include a copy of this
+    License with every copy of the Source Code form of the Covered
+    Software You distribute or otherwise make available.  You must
+    inform recipients of any such Covered Software in Executable form
+    as to how they can obtain such Covered Software in Source Code
+    form in a reasonable manner on or through a medium customarily
+    used for software exchange.
+
+    3.2. Modifications.
+
+    The Modifications that You create or to which You contribute are
+    governed by the terms of this License.  You represent that You
+    believe Your Modifications are Your original creation(s) and/or
+    You have sufficient rights to grant the rights conveyed by this
+    License.
+
+    3.3. Required Notices.
+
+    You must include a notice in each of Your Modifications that
+    identifies You as the Contributor of the Modification.  You may
+    not remove or alter any copyright, patent or trademark notices
+    contained within the Covered Software, or any notices of licensing
+    or any descriptive text giving attribution to any Contributor or
+    the Initial Developer.
+
+    3.4. Application of Additional Terms.
+
+    You may not offer or impose any terms on any Covered Software in
+    Source Code form that alters or restricts the applicable version
+    of this License or the recipients' rights hereunder.  You may
+    choose to offer, and to charge a fee for, warranty, support,
+    indemnity or liability obligations to one or more recipients of
+    Covered Software.  However, you may do so only on Your own behalf,
+    and not on behalf of the Initial Developer or any Contributor.
+    You must make it absolutely clear that any such warranty, support,
+    indemnity or liability obligation is offered by You alone, and You
+    hereby agree to indemnify the Initial Developer and every
+    Contributor for any liability incurred by the Initial Developer or
+    such Contributor as a result of warranty, support, indemnity or
+    liability terms You offer.
+
+    3.5. Distribution of Executable Versions.
+
+    You may distribute the Executable form of the Covered Software
+    under the terms of this License or under the terms of a license of
+    Your choice, which may contain terms different from this License,
+    provided that You are in compliance with the terms of this License
+    and that the license for the Executable form does not attempt to
+    limit or alter the recipient's rights in the Source Code form from
+    the rights set forth in this License.  If You distribute the
+    Covered Software in Executable form under a different license, You
+    must make it absolutely clear that any terms which differ from
+    this License are offered by You alone, not by the Initial
+    Developer or Contributor.  You hereby agree to indemnify the
+    Initial Developer and every Contributor for any liability incurred
+    by the Initial Developer or such Contributor as a result of any
+    such terms You offer.
+
+    3.6. Larger Works.
+
+    You may create a Larger Work by combining Covered Software with
+    other code not governed by the terms of this License and
+    distribute the Larger Work as a single product.  In such a case,
+    You must make sure the requirements of this License are fulfilled
+    for the Covered Software.
+
+4. Versions of the License.
+
+    4.1. New Versions.
+
+    Sun Microsystems, Inc. is the initial license steward and may
+    publish revised and/or new versions of this License from time to
+    time.  Each version will be given a distinguishing version number.
+    Except as provided in Section 4.3, no one other than the license
+    steward has the right to modify this License.
+
+    4.2. Effect of New Versions.
+
+    You may always continue to use, distribute or otherwise make the
+    Covered Software available under the terms of the version of the
+    License under which You originally received the Covered Software.
+    If the Initial Developer includes a notice in the Original
+    Software prohibiting it from being distributed or otherwise made
+    available under any subsequent version of the License, You must
+    distribute and make the Covered Software available under the terms
+    of the version of the License under which You originally received
+    the Covered Software.  Otherwise, You may also choose to use,
+    distribute or otherwise make the Covered Software available under
+    the terms of any subsequent version of the License published by
+    the license steward.
+
+    4.3. Modified Versions.
+
+    When You are an Initial Developer and You want to create a new
+    license for Your Original Software, You may create and use a
+    modified version of this License if You: (a) rename the license
+    and remove any references to the name of the license steward
+    (except to note that the license differs from this License); and
+    (b) otherwise make it clear that the license contains terms which
+    differ from this License.
+
+5. DISCLAIMER OF WARRANTY.
+
+    COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS"
+    BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+    INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED
+    SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
+    PURPOSE OR NON-INFRINGING.  THE ENTIRE RISK AS TO THE QUALITY AND
+    PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU.  SHOULD ANY
+    COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
+    INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
+    NECESSARY SERVICING, REPAIR OR CORRECTION.  THIS DISCLAIMER OF
+    WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.  NO USE OF
+    ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS
+    DISCLAIMER.
+
+6. TERMINATION.
+
+    6.1. This License and the rights granted hereunder will terminate
+    automatically if You fail to comply with terms herein and fail to
+    cure such breach within 30 days of becoming aware of the breach.
+    Provisions which, by their nature, must remain in effect beyond
+    the termination of this License shall survive.
+
+    6.2. If You assert a patent infringement claim (excluding
+    declaratory judgment actions) against Initial Developer or a
+    Contributor (the Initial Developer or Contributor against whom You
+    assert such claim is referred to as "Participant") alleging that
+    the Participant Software (meaning the Contributor Version where
+    the Participant is a Contributor or the Original Software where
+    the Participant is the Initial Developer) directly or indirectly
+    infringes any patent, then any and all rights granted directly or
+    indirectly to You by such Participant, the Initial Developer (if
+    the Initial Developer is not the Participant) and all Contributors
+    under Sections 2.1 and/or 2.2 of this License shall, upon 60 days
+    notice from Participant terminate prospectively and automatically
+    at the expiration of such 60 day notice period, unless if within
+    such 60 day period You withdraw Your claim with respect to the
+    Participant Software against such Participant either unilaterally
+    or pursuant to a written agreement with Participant.
+
+    6.3. In the event of termination under Sections 6.1 or 6.2 above,
+    all end user licenses that have been validly granted by You or any
+    distributor hereunder prior to termination (excluding licenses
+    granted to You by any distributor) shall survive termination.
+
+7. LIMITATION OF LIABILITY.
+
+    UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+    (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
+    INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
+    COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE
+    LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
+    CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
+    LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK
+    STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+    COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+    INFORMED OF THE POSSIBILITY OF SUCH DAMAGES.  THIS LIMITATION OF
+    LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL
+    INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT
+    APPLICABLE LAW PROHIBITS SUCH LIMITATION.  SOME JURISDICTIONS DO
+    NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR
+    CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT
+    APPLY TO YOU.
+
+8. U.S. GOVERNMENT END USERS.
+
+    The Covered Software is a "commercial item," as that term is
+    defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
+    computer software" (as that term is defined at 48
+    C.F.R. 252.227-7014(a)(1)) and "commercial computer software
+    documentation" as such terms are used in 48 C.F.R. 12.212
+    (Sept. 1995).  Consistent with 48 C.F.R. 12.212 and 48
+    C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
+    U.S. Government End Users acquire Covered Software with only those
+    rights set forth herein.  This U.S. Government Rights clause is in
+    lieu of, and supersedes, any other FAR, DFAR, or other clause or
+    provision that addresses Government rights in computer software
+    under this License.
+
+9. MISCELLANEOUS.
+
+    This License represents the complete agreement concerning subject
+    matter hereof.  If any provision of this License is held to be
+    unenforceable, such provision shall be reformed only to the extent
+    necessary to make it enforceable.  This License shall be governed
+    by the law of the jurisdiction specified in a notice contained
+    within the Original Software (except to the extent applicable law,
+    if any, provides otherwise), excluding such jurisdiction's
+    conflict-of-law provisions.  Any litigation relating to this
+    License shall be subject to the jurisdiction of the courts located
+    in the jurisdiction and venue specified in a notice contained
+    within the Original Software, with the losing party responsible
+    for costs, including, without limitation, court costs and
+    reasonable attorneys' fees and expenses.  The application of the
+    United Nations Convention on Contracts for the International Sale
+    of Goods is expressly excluded.  Any law or regulation which
+    provides that the language of a contract shall be construed
+    against the drafter shall not apply to this License.  You agree
+    that You alone are responsible for compliance with the United
+    States export administration regulations (and the export control
+    laws and regulation of any other countries) when You use,
+    distribute or otherwise make available any Covered Software.
+
+10. RESPONSIBILITY FOR CLAIMS.
+
+    As between Initial Developer and the Contributors, each party is
+    responsible for claims and damages arising, directly or
+    indirectly, out of its utilization of rights under this License
+    and You agree to work with Initial Developer and Contributors to
+    distribute such responsibility on an equitable basis.  Nothing
+    herein is intended or shall be deemed to constitute any admission
+    of liability.
+
+--------------------------------------------------------------------
+
+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND
+DISTRIBUTION LICENSE (CDDL)
+
+For Covered Software in this distribution, this License shall
+be governed by the laws of the State of California (excluding
+conflict-of-law provisions).
+
+Any litigation relating to this License shall be subject to the
+jurisdiction of the Federal Courts of the Northern District of
+California and the state courts of the State of California, with
+venue lying in Santa Clara County, California.
diff --git a/vendor/github.com/howeyc/gopass/README.md b/vendor/github.com/howeyc/gopass/README.md
new file mode 100644
index 0000000..d9bd8e5
--- /dev/null
+++ b/vendor/github.com/howeyc/gopass/README.md
@@ -0,0 +1,3 @@
+# getpasswd in Go [![GoDoc](https://godoc.org/github.com/howeyc/gopass?status.svg)](https://godoc.org/github.com/howeyc/gopass) [![Build Status](https://secure.travis-ci.org/howeyc/gopass.png?branch=master)](http://travis-ci.org/howeyc/gopass)
+
+You should probably just use [terminal](https://golang.org/x/crypto/ssh/terminal).
diff --git a/vendor/github.com/howeyc/gopass/pass.go b/vendor/github.com/howeyc/gopass/pass.go
new file mode 100644
index 0000000..0e2cfce
--- /dev/null
+++ b/vendor/github.com/howeyc/gopass/pass.go
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2012 Chris Howey
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package gopass
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"os"
+)
+
+type FdReader interface {
+	io.Reader
+	Fd() uintptr
+}
+
+var defaultGetCh = func(r io.Reader) (byte, error) {
+	buf := make([]byte, 1)
+	if n, err := r.Read(buf); n == 0 || err != nil {
+		if err != nil {
+			return 0, err
+		}
+		return 0, io.EOF
+	}
+	return buf[0], nil
+}
+
+var (
+	maxLength            = 512
+	ErrInterrupted       = errors.New("interrupted")
+	ErrMaxLengthExceeded = fmt.Errorf("maximum byte limit (%v) exceeded", maxLength)
+
+	// Provide variable so that tests can provide a mock implementation.
+	getch = defaultGetCh
+)
+
+// getPasswd returns the input read from terminal.
+// If prompt is not empty, it will be output as a prompt to the user
+// If masked is true, typing will be matched by asterisks on the screen.
+// Otherwise, typing will echo nothing.
+func getPasswd(prompt string, masked bool, r FdReader, w io.Writer) ([]byte, error) {
+	var err error
+	var pass, bs, mask []byte
+	if masked {
+		bs = []byte("\b \b")
+		mask = []byte("*")
+	}
+
+	if isTerminal(r.Fd()) {
+		if oldState, err := makeRaw(r.Fd()); err != nil {
+			return pass, err
+		} else {
+			defer func() {
+				restore(r.Fd(), oldState)
+				fmt.Fprintln(w)
+			}()
+		}
+	}
+
+	if prompt != "" {
+		fmt.Fprint(w, prompt)
+	}
+
+	// Track total bytes read, not just bytes in the password.  This ensures any
+	// errors that might flood the console with nil or -1 bytes infinitely are
+	// capped.
+	var counter int
+	for counter = 0; counter <= maxLength; counter++ {
+		if v, e := getch(r); e != nil {
+			err = e
+			break
+		} else if v == 127 || v == 8 {
+			if l := len(pass); l > 0 {
+				pass = pass[:l-1]
+				fmt.Fprint(w, string(bs))
+			}
+		} else if v == 13 || v == 10 {
+			break
+		} else if v == 3 {
+			err = ErrInterrupted
+			break
+		} else if v != 0 {
+			pass = append(pass, v)
+			fmt.Fprint(w, string(mask))
+		}
+	}
+
+	if counter > maxLength {
+		err = ErrMaxLengthExceeded
+	}
+
+	return pass, err
+}
+
+// GetPasswd returns the password read from the terminal without echoing input.
+// The returned byte array does not include end-of-line characters.
+func GetPasswd() ([]byte, error) {
+	return getPasswd("", false, os.Stdin, os.Stdout)
+}
+
+// GetPasswdMasked returns the password read from the terminal, echoing asterisks.
+// The returned byte array does not include end-of-line characters.
+func GetPasswdMasked() ([]byte, error) {
+	return getPasswd("", true, os.Stdin, os.Stdout)
+}
+
+// GetPasswdPrompt prompts the user and returns the password read from the terminal.
+// If mask is true, then asterisks are echoed.
+// The returned byte array does not include end-of-line characters.
+func GetPasswdPrompt(prompt string, mask bool, r FdReader, w io.Writer) ([]byte, error) {
+	return getPasswd(prompt, mask, r, w)
+}
diff --git a/vendor/github.com/howeyc/gopass/terminal.go b/vendor/github.com/howeyc/gopass/terminal.go
new file mode 100644
index 0000000..1b1d23b
--- /dev/null
+++ b/vendor/github.com/howeyc/gopass/terminal.go
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012 Chris Howey
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+// +build !solaris
+
+package gopass
+
+import "golang.org/x/crypto/ssh/terminal"
+
+type terminalState struct {
+	state *terminal.State
+}
+
+func isTerminal(fd uintptr) bool {
+	return terminal.IsTerminal(int(fd))
+}
+
+func makeRaw(fd uintptr) (*terminalState, error) {
+	state, err := terminal.MakeRaw(int(fd))
+
+	return &terminalState{
+		state: state,
+	}, err
+}
+
+func restore(fd uintptr, oldState *terminalState) error {
+	return terminal.Restore(int(fd), oldState.state)
+}
diff --git a/vendor/github.com/howeyc/gopass/terminal_solaris.go b/vendor/github.com/howeyc/gopass/terminal_solaris.go
new file mode 100644
index 0000000..257e1b4
--- /dev/null
+++ b/vendor/github.com/howeyc/gopass/terminal_solaris.go
@@ -0,0 +1,69 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+// Below is derived from Solaris source, so CDDL license is included.
+
+package gopass
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+type terminalState struct {
+	state *unix.Termios
+}
+
+// isTerminal returns true if there is a terminal attached to the given
+// file descriptor.
+// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
+func isTerminal(fd uintptr) bool {
+	var termio unix.Termio
+	err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
+	return err == nil
+}
+
+// makeRaw puts the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
+func makeRaw(fd uintptr) (*terminalState, error) {
+	oldTermiosPtr, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
+	if err != nil {
+		return nil, err
+	}
+	oldTermios := *oldTermiosPtr
+
+	newTermios := oldTermios
+	newTermios.Lflag &^= syscall.ECHO | syscall.ECHOE | syscall.ECHOK | syscall.ECHONL
+	if err := unix.IoctlSetTermios(int(fd), unix.TCSETS, &newTermios); err != nil {
+		return nil, err
+	}
+
+	return &terminalState{
+		state: oldTermiosPtr,
+	}, nil
+}
+
+func restore(fd uintptr, oldState *terminalState) error {
+	return unix.IoctlSetTermios(int(fd), unix.TCSETS, oldState.state)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 02ce460..a61528e 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -62,6 +62,8 @@ github.com/google/go-cmp/cmp
 github.com/google/go-cmp/cmp/internal/diff
 github.com/google/go-cmp/cmp/internal/function
 github.com/google/go-cmp/cmp/internal/value
+# github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c
+github.com/howeyc/gopass
 # github.com/inconshreveable/mousetrap v1.0.0
 github.com/inconshreveable/mousetrap
 # github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99