1
0
mirror of https://github.com/drone/drone-cli.git synced 2026-01-24 11:48:01 +01:00

enable remote secret management

This commit is contained in:
Brad Rydzewski 2018-10-21 12:18:43 -07:00
parent c221ce73e2
commit b2aebbf41b
12 changed files with 420 additions and 8 deletions

2
Gopkg.lock generated

@ -84,7 +84,7 @@
"plugin/logger",
"plugin/secret"
]
revision = "d00b5c24549e5676acefedc4d5ef115471bf48eb"
revision = "a02047a0b54dae0f23b511367c12c528606b599e"
[[projects]]
branch = "master"

@ -20,7 +20,11 @@ var Command = cli.Command{
Flags: []cli.Flag{
cli.BoolFlag{
Name: "allow-pull-request",
Usage: "permit access to pull requests",
Usage: "permit read access to pull requests",
},
cli.BoolFlag{
Name: "allow-push-on-pull-request",
Usage: "permit write access to pull requests (e.g. allow docker push)",
},
},
}
@ -47,8 +51,9 @@ func encryptSecret(c *cli.Context) error {
}
secret := &drone.Secret{
Data: plaintext,
Pull: c.Bool("allow-pull-request"),
Data: plaintext,
PullRequest: c.Bool("allow-pull-request"),
PullRequestPush: c.Bool("allow-push-on-pull-request"),
}
encrypted, err := client.Encrypt(owner, name, secret)
if err != nil {

@ -15,6 +15,7 @@ import (
"github.com/drone/drone-cli/drone/log"
"github.com/drone/drone-cli/drone/plugins"
"github.com/drone/drone-cli/drone/repo"
"github.com/drone/drone-cli/drone/secret"
"github.com/drone/drone-cli/drone/server"
"github.com/drone/drone-cli/drone/sign"
"github.com/drone/drone-cli/drone/user"
@ -77,6 +78,7 @@ func main() {
info.Command,
repo.Command,
user.Command,
secret.Command,
server.Command,
autoscale.Command,
format.Command,

16
drone/secret/secret.go Normal file

@ -0,0 +1,16 @@
package secret
import "github.com/urfave/cli"
// Command exports the secret command.
var Command = cli.Command{
Name: "secret",
Usage: "manage secrets",
Subcommands: []cli.Command{
secretCreateCmd,
secretDeleteCmd,
secretUpdateCmd,
secretInfoCmd,
secretListCmd,
},
}

@ -0,0 +1,72 @@
package secret
import (
"io/ioutil"
"strings"
"github.com/drone/drone-cli/drone/internal"
"github.com/drone/drone-go/drone"
"github.com/urfave/cli"
)
var secretCreateCmd = cli.Command{
Name: "add",
Usage: "adds a secret",
ArgsUsage: "[repo/name]",
Action: secretCreate,
Flags: []cli.Flag{
cli.StringFlag{
Name: "repository",
Usage: "repository name (e.g. octocat/hello-world)",
},
cli.StringFlag{
Name: "name",
Usage: "secret name",
},
cli.StringFlag{
Name: "data",
Usage: "secret value",
},
cli.BoolFlag{
Name: "allow-pull-request",
Usage: "permit read access to pull requests",
},
cli.BoolFlag{
Name: "allow-push-on-pull-request",
Usage: "permit write access to pull requests (e.g. allow docker push)",
},
},
}
func secretCreate(c *cli.Context) error {
reponame := c.String("repository")
if reponame == "" {
reponame = c.Args().First()
}
owner, name, err := internal.ParseRepo(reponame)
if err != nil {
return err
}
client, err := internal.NewClient(c)
if err != nil {
return err
}
secret := &drone.Secret{
Name: c.String("name"),
Data: c.String("data"),
PullRequest: c.Bool("allow-pull-request"),
PullRequestPush: c.Bool("allow-push-on-pull-request"),
}
if strings.HasPrefix(secret.Data, "@") {
path := strings.TrimPrefix(secret.Data, "@")
out, ferr := ioutil.ReadFile(path)
if ferr != nil {
return ferr
}
secret.Data = string(out)
}
_, err = client.SecretCreate(owner, name, secret)
return err
}

@ -0,0 +1,61 @@
package secret
import (
"html/template"
"os"
"github.com/urfave/cli"
"github.com/drone/drone-cli/drone/internal"
)
var secretInfoCmd = cli.Command{
Name: "info",
Usage: "display secret info",
ArgsUsage: "[repo/name]",
Action: secretInfo,
Flags: []cli.Flag{
cli.StringFlag{
Name: "repository",
Usage: "repository name (e.g. octocat/hello-world)",
},
cli.StringFlag{
Name: "name",
Usage: "secret name",
},
cli.StringFlag{
Name: "format",
Usage: "format output",
Value: tmplSecretList,
Hidden: true,
},
},
}
func secretInfo(c *cli.Context) error {
var (
secretName = c.String("name")
repoName = c.String("repository")
format = c.String("format") + "\n"
)
if repoName == "" {
repoName = c.Args().First()
}
owner, name, err := internal.ParseRepo(repoName)
if err != nil {
return err
}
client, err := internal.NewClient(c)
if err != nil {
return err
}
secret, err := client.Secret(owner, name, secretName)
if err != nil {
return err
}
tmpl, err := template.New("_").Parse(format)
if err != nil {
return err
}
return tmpl.Execute(os.Stdout, secret)
}

@ -0,0 +1,65 @@
package secret
import (
"html/template"
"os"
"github.com/urfave/cli"
"github.com/drone/drone-cli/drone/internal"
)
var secretListCmd = cli.Command{
Name: "ls",
Usage: "list secrets",
ArgsUsage: "[repo/name]",
Action: secretList,
Flags: []cli.Flag{
cli.StringFlag{
Name: "repository",
Usage: "repository name (e.g. octocat/hello-world)",
},
cli.StringFlag{
Name: "format",
Usage: "format output",
Value: tmplSecretList,
Hidden: true,
},
},
}
func secretList(c *cli.Context) error {
var (
format = c.String("format") + "\n"
reponame = c.String("repository")
)
if reponame == "" {
reponame = c.Args().First()
}
owner, name, err := internal.ParseRepo(reponame)
if err != nil {
return err
}
client, err := internal.NewClient(c)
if err != nil {
return err
}
list, err := client.SecretList(owner, name)
if err != nil {
return err
}
tmpl, err := template.New("_").Parse(format)
if err != nil {
return err
}
for _, secret := range list {
tmpl.Execute(os.Stdout, secret)
}
return nil
}
// template for secret list items
var tmplSecretList = "\x1b[33m{{ .Name }} \x1b[0m" + `
Pull Request Read: {{ .PullRequest }}
Pull Request Write: {{ .PullRequestPush }}
`

43
drone/secret/secret_rm.go Normal file

@ -0,0 +1,43 @@
package secret
import (
"github.com/urfave/cli"
"github.com/drone/drone-cli/drone/internal"
)
var secretDeleteCmd = cli.Command{
Name: "rm",
Usage: "remove a secret",
ArgsUsage: "[repo/name]",
Action: secretDelete,
Flags: []cli.Flag{
cli.StringFlag{
Name: "repository",
Usage: "repository name (e.g. octocat/hello-world)",
},
cli.StringFlag{
Name: "name",
Usage: "secret name",
},
},
}
func secretDelete(c *cli.Context) error {
var (
secret = c.String("name")
reponame = c.String("repository")
)
if reponame == "" {
reponame = c.Args().First()
}
owner, name, err := internal.ParseRepo(reponame)
if err != nil {
return err
}
client, err := internal.NewClient(c)
if err != nil {
return err
}
return client.SecretDelete(owner, name, secret)
}

@ -0,0 +1,71 @@
package secret
import (
"io/ioutil"
"strings"
"github.com/drone/drone-cli/drone/internal"
"github.com/drone/drone-go/drone"
"github.com/urfave/cli"
)
var secretUpdateCmd = cli.Command{
Name: "update",
Usage: "update a secret",
ArgsUsage: "[repo/name]",
Action: secretUpdate,
Flags: []cli.Flag{
cli.StringFlag{
Name: "repository",
Usage: "repository name (e.g. octocat/hello-world)",
},
cli.StringFlag{
Name: "name",
Usage: "secret name",
},
cli.StringFlag{
Name: "data",
Usage: "secret value",
},
cli.BoolFlag{
Name: "allow-pull-request",
Usage: "permit read access to pull requests",
},
cli.BoolFlag{
Name: "allow-push-on-pull-request",
Usage: "permit write access to pull requests (e.g. allow docker push)",
},
},
}
func secretUpdate(c *cli.Context) error {
reponame := c.String("repository")
if reponame == "" {
reponame = c.Args().First()
}
owner, name, err := internal.ParseRepo(reponame)
if err != nil {
return err
}
client, err := internal.NewClient(c)
if err != nil {
return err
}
secret := &drone.Secret{
Name: c.String("name"),
Data: c.String("data"),
PullRequest: c.Bool("allow-pull-request"),
PullRequestPush: c.Bool("allow-push-on-pull-request"),
}
if strings.HasPrefix(secret.Data, "@") {
path := strings.TrimPrefix(secret.Data, "@")
out, ferr := ioutil.ReadFile(path)
if ferr != nil {
return ferr
}
secret.Data = string(out)
}
_, err = client.SecretUpdate(owner, name, secret)
return err
}

@ -333,6 +333,44 @@ func (c *client) Encrypt(owner, name string, secret *Secret) (string, error) {
return out.Data, err
}
// Secret returns a secret by name.
func (c *client) Secret(owner, name, secret string) (*Secret, error) {
out := new(Secret)
uri := fmt.Sprintf(pathRepoSecret, c.addr, owner, name, secret)
err := c.get(uri, out)
return out, err
}
// SecretList returns a list of all repository secrets.
func (c *client) SecretList(owner string, name string) ([]*Secret, error) {
var out []*Secret
uri := fmt.Sprintf(pathRepoSecrets, c.addr, owner, name)
err := c.get(uri, &out)
return out, err
}
// SecretCreate creates a secret.
func (c *client) SecretCreate(owner, name string, in *Secret) (*Secret, error) {
out := new(Secret)
uri := fmt.Sprintf(pathRepoSecrets, c.addr, owner, name)
err := c.post(uri, in, out)
return out, err
}
// SecretUpdate updates a secret.
func (c *client) SecretUpdate(owner, name string, in *Secret) (*Secret, error) {
out := new(Secret)
uri := fmt.Sprintf(pathRepoSecret, c.addr, owner, name, in.Name)
err := c.patch(uri, in, out)
return out, err
}
// SecretDelete deletes a secret.
func (c *client) SecretDelete(owner, name, secret string) error {
uri := fmt.Sprintf(pathRepoSecret, c.addr, owner, name, secret)
return c.delete(uri)
}
// Cron returns a cronjob by name.
func (c *client) Cron(owner, name, cron string) (*Cron, error) {
out := new(Cron)
@ -349,6 +387,20 @@ func (c *client) CronList(owner string, name string) ([]*Cron, error) {
return out, err
}
// CronCreate creates a cronjob.
func (c *client) CronCreate(owner, name string, in *Cron) (*Cron, error) {
out := new(Cron)
uri := fmt.Sprintf(pathCrons, c.addr, owner, name)
err := c.post(uri, in, out)
return out, err
}
// CronDelete deletes a cronjob.
func (c *client) CronDelete(owner, name, cron string) error {
uri := fmt.Sprintf(pathCron, c.addr, owner, name, cron)
return c.delete(uri)
}
// CronEnable ensables a cronjob.
func (c *client) CronEnable(owner, name, cron string) error {
uri := fmt.Sprintf(pathCron, c.addr, owner, name, cron)

@ -114,12 +114,33 @@ type Client interface {
// LogsPurge purges the build logs for the specified step.
LogsPurge(owner, name string, build, stage, step int) error
// Secret returns a secret by name.
Secret(owner, name, secret string) (*Secret, error)
// SecretList returns a list of all repository secrets.
SecretList(owner, name string) ([]*Secret, error)
// SecretCreate creates a registry.
SecretCreate(owner, name string, secret *Secret) (*Secret, error)
// SecretUpdate updates a registry.
SecretUpdate(owner, name string, secret *Secret) (*Secret, error)
// SecretDelete deletes a secret.
SecretDelete(owner, name, secret string) error
// Cron returns a cronjob by name.
Cron(owner, name, cron string) (*Cron, error)
// CronList returns a list of all repository cronjobs.
CronList(owner string, name string) ([]*Cron, error)
// CronCreate creates a cronjob.
CronCreate(owner, name string, in *Cron) (*Cron, error)
// CronDelete deletes a cronjob.
CronDelete(owner, name, cron string) error
// CronEnable enables a cronjob.
CronEnable(owner, name, cron string) error

@ -161,10 +161,14 @@ type (
// Secret represents a secret variable, such as a password or token.
Secret struct {
Name string `json:"name,omitempty"`
Data string `json:"data,omitempty"`
Pull bool `json:"pull,omitempty"`
Fork bool `json:"fork,omitempty"`
Name string `json:"name,omitempty"`
Data string `json:"data,omitempty"`
PullRequest bool `json:"pull_request,omitempty"`
PullRequestPush bool `json:"pull_request_push,omitempty"`
// Deprecated.
Pull bool `json:"pull,omitempty"`
Fork bool `json:"fork,omitempty"`
}
// Server represents a server node.