Skip to content
This repository was archived by the owner on Feb 16, 2023. It is now read-only.

Commit 7864ec6

Browse files
committed
Merge remote-tracking branch 'origin/develop' into feature/aws-ls-help
2 parents f8d62d0 + b752218 commit 7864ec6

64 files changed

Lines changed: 574 additions & 141 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

internals/demo/app/page.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package app
2+
3+
const page = `
4+
<!doctype html>
5+
<html lang="en">
6+
<head>
7+
<meta charset="utf-8">
8+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
9+
<meta name="description" content="">
10+
<meta name="author" content="">
11+
<link rel="icon" href="https://secrethub.io/img/favicon/favicon.ico">
12+
13+
<title>SecretHub Example App</title>
14+
15+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.10.2/css/all.min.css" integrity="sha256-zmfNZmXoNWBMemUOo1XUGFfc0ihGGLYdgtJS3KCr/l0=" crossorigin="anonymous" />
16+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
17+
18+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
19+
20+
<style>
21+
html,
22+
body {
23+
height: 100%;
24+
}
25+
26+
body {
27+
display: -ms-flexbox;
28+
display: -webkit-box;
29+
display: flex;
30+
-ms-flex-align: center;
31+
-ms-flex-pack: center;
32+
-webkit-box-align: center;
33+
align-items: center;
34+
-webkit-box-pack: center;
35+
justify-content: center;
36+
padding-top: 40px;
37+
padding-bottom: 40px;
38+
background-color: #f5f5f5;
39+
}
40+
41+
.container {
42+
width: 100%;
43+
max-width: 400px;
44+
padding: 15px;
45+
margin: 0 auto;
46+
}
47+
</style>
48+
49+
<script>
50+
function processResult(status, icon, color, result){
51+
$("#status").html(status);
52+
$("#animation").attr("class", "fas fa-"+icon+" fa-5x");
53+
$("#animation").css("color", color);
54+
if(result !== "") {
55+
$(".result-container").attr("hidden",false);
56+
try {
57+
j = JSON.parse(result);
58+
$("#result").html(j['message']);
59+
} catch (e) {
60+
$("#result").html(result);
61+
}
62+
}
63+
}
64+
65+
function processError(message){
66+
processResult("An error occurred!", "times", "red", message);
67+
}
68+
69+
$(function(){
70+
$.get("/api", {}, function(res, status, xhr){
71+
if(xhr.status === 200) {
72+
processResult("Successfully connected to https://demo.secrethub.io/api!", "check", "green", res);
73+
} else {
74+
console.log(res, status, xhr);
75+
processError(res);
76+
}
77+
}).catch(function(res){
78+
processError(res.responseText);
79+
});
80+
});
81+
</script>
82+
</head>
83+
84+
<body class="text-center">
85+
<div class="container">
86+
<img class="mb-4" src="https://secrethub.io/img/secrethub-logo-rgb-shield-square.png" alt="SecretHub logo" width="60" height="60">
87+
<h1 class="h3 mb-3 font-weight-normal">Demo App</h1>
88+
<i id="animation" class="fas fa-spinner fa-spin fa-3x"> </i>
89+
<p id="status">Trying to connect to https://demo.secrethub.io/api...</p>
90+
<div class="result-container mt-3 card" hidden>
91+
<div class="card-header">
92+
Result
93+
</div>
94+
<div class="card-body" id="result">
95+
</div>
96+
</div>
97+
<p class="mt-5 mb-3 text-muted">Read the <a href="https://secrethub.io/docs/reference/cli/demo/" target="_blank">documentation</a> for this app</p>
98+
</div>
99+
</body>
100+
</html>
101+
`

internals/demo/app/serve.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package app
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"net/http"
7+
"os"
8+
)
9+
10+
type Server struct {
11+
host string
12+
port int
13+
14+
appUsername string
15+
appPassword string
16+
}
17+
18+
func NewServer(host string, port int) *Server {
19+
username := os.Getenv("DEMO_USERNAME")
20+
password := os.Getenv("DEMO_PASSWORD")
21+
22+
return &Server{
23+
host: host,
24+
port: port,
25+
appUsername: username,
26+
appPassword: password,
27+
}
28+
}
29+
30+
func (s *Server) Serve() error {
31+
http.HandleFunc("/", s.ServeIndex)
32+
http.HandleFunc("/api", s.ServeAPI)
33+
34+
addr := fmt.Sprintf("%s:%d", s.host, s.port)
35+
return http.ListenAndServe(addr, nil)
36+
}
37+
38+
func (s *Server) ServeIndex(w http.ResponseWriter, r *http.Request) {
39+
_, err := w.Write([]byte(page))
40+
if err != nil {
41+
w.WriteHeader(http.StatusInternalServerError)
42+
}
43+
}
44+
45+
func (s *Server) ServeAPI(w http.ResponseWriter, r *http.Request) {
46+
w.Header().Add("Access-Control-Allow-Origin", "*")
47+
48+
if s.appUsername == "" {
49+
writeServerError(w, "DEMO_USERNAME environment variable not set")
50+
return
51+
}
52+
53+
if s.appPassword == "" {
54+
writeServerError(w, "DEMO_PASSWORD environment variable not set")
55+
return
56+
}
57+
58+
req, err := http.NewRequest("GET", "https://demo.secrethub.io/api/v1/basic-auth", nil)
59+
if err != nil {
60+
writeServerError(w, err.Error())
61+
return
62+
}
63+
64+
req.SetBasicAuth(s.appUsername, s.appPassword)
65+
resp, err := http.DefaultClient.Do(req)
66+
if err != nil {
67+
writeServerError(w, err.Error())
68+
return
69+
}
70+
w.WriteHeader(resp.StatusCode)
71+
_, err = io.Copy(w, resp.Body)
72+
if err != nil {
73+
panic(err)
74+
}
75+
}
76+
77+
func writeServerError(w http.ResponseWriter, message string) {
78+
w.WriteHeader(http.StatusInternalServerError)
79+
fmt.Fprint(w, message)
80+
}

internals/demo/command.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package demo
2+
3+
import (
4+
"github.com/secrethub/secrethub-cli/internals/cli/ui"
5+
"github.com/secrethub/secrethub-cli/internals/secrethub/command"
6+
)
7+
8+
// Command is a command to run the secrethub example app.
9+
type Command struct {
10+
io ui.IO
11+
newClient newClientFunc
12+
}
13+
14+
// NewCommand creates a new example app command.
15+
func NewCommand(io ui.IO, newClient newClientFunc) *Command {
16+
return &Command{
17+
io: io,
18+
newClient: newClient,
19+
}
20+
}
21+
22+
// Register registers the command, arguments and flags on the provided Registerer.
23+
func (cmd *Command) Register(r command.Registerer) {
24+
clause := r.Command("demo", "Manage the demo application.")
25+
clause.Hidden()
26+
27+
NewInitCommand(cmd.io, cmd.newClient).Register(clause)
28+
NewServeCommand(cmd.io).Register(clause)
29+
}

internals/demo/init.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package demo
2+
3+
import (
4+
"crypto/hmac"
5+
"crypto/sha256"
6+
"encoding/base64"
7+
"fmt"
8+
9+
"github.com/secrethub/secrethub-cli/internals/cli/ui"
10+
"github.com/secrethub/secrethub-cli/internals/secrethub/command"
11+
12+
"github.com/secrethub/secrethub-go/internals/api"
13+
"github.com/secrethub/secrethub-go/pkg/secrethub"
14+
"github.com/secrethub/secrethub-go/pkg/secretpath"
15+
)
16+
17+
type newClientFunc func() (secrethub.ClientInterface, error)
18+
19+
const defaultDemoRepo = "demo"
20+
21+
type InitCommand struct {
22+
repo api.RepoPath
23+
24+
io ui.IO
25+
newClient newClientFunc
26+
}
27+
28+
func NewInitCommand(io ui.IO, newClient newClientFunc) *InitCommand {
29+
return &InitCommand{
30+
io: io,
31+
newClient: newClient,
32+
}
33+
}
34+
35+
// Register registers the command, arguments and flags on the provided Registerer.
36+
func (cmd *InitCommand) Register(r command.Registerer) {
37+
clause := r.Command("init", "Create the secrets necessary to connect with the demo application.")
38+
clause.HelpLong("demo init creates a repository with the username and password needed to connect to the demo API.")
39+
40+
clause.Flag("repo", "The path of the repository to create. Defaults to a "+defaultDemoRepo+" repo in your personal namespace.").SetValue(&cmd.repo)
41+
42+
command.BindAction(clause, cmd.Run)
43+
}
44+
45+
// Run handles the command with the options as specified in the command.
46+
func (cmd *InitCommand) Run() error {
47+
client, err := cmd.newClient()
48+
if err != nil {
49+
return err
50+
}
51+
52+
var repoPath string
53+
var username string
54+
if cmd.repo == "" {
55+
me, err := client.Me().GetUser()
56+
if err != nil {
57+
return err
58+
}
59+
username = me.Username
60+
repoPath = secretpath.Join(me.Username, defaultDemoRepo)
61+
} else {
62+
username = secretpath.Namespace(cmd.repo.Value())
63+
repoPath = cmd.repo.Value()
64+
}
65+
66+
_, err = client.Repos().Create(repoPath)
67+
if err == api.ErrRepoAlreadyExists && cmd.repo == "" {
68+
return fmt.Errorf("demo repo %s already exists, use --repo to specify another repo to use", repoPath)
69+
} else if err != nil {
70+
return err
71+
}
72+
73+
usernamePath := secretpath.Join(repoPath, "username")
74+
_, err = client.Secrets().Write(usernamePath, []byte(username))
75+
if err != nil {
76+
return err
77+
}
78+
79+
h := hmac.New(sha256.New, []byte("this-is-no-good-way-to-generate-a-password-that-is-why-we-only-use-it-for-demo-purposes"))
80+
password := base64.RawStdEncoding.EncodeToString(h.Sum([]byte(username)))[:20]
81+
82+
passwordPath := secretpath.Join(repoPath, "password")
83+
_, err = client.Secrets().Write(passwordPath, []byte(password))
84+
if err != nil {
85+
return err
86+
}
87+
88+
fmt.Printf("Created the following secrets:\n%s\n%s\n", usernamePath, passwordPath)
89+
90+
return nil
91+
}

internals/demo/serve.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package demo
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/secrethub/secrethub-cli/internals/cli/ui"
7+
"github.com/secrethub/secrethub-cli/internals/demo/app"
8+
"github.com/secrethub/secrethub-cli/internals/secrethub/command"
9+
)
10+
11+
type ServeCommand struct {
12+
io ui.IO
13+
14+
host string
15+
port int
16+
}
17+
18+
func NewServeCommand(io ui.IO) *ServeCommand {
19+
return &ServeCommand{
20+
io: io,
21+
}
22+
}
23+
24+
// Register registers the command, arguments and flags on the provided Registerer.
25+
func (cmd *ServeCommand) Register(r command.Registerer) {
26+
clause := r.Command("serve", "Runs the secrethub example by serving a web page.")
27+
28+
clause.Flag("host", "The host to serve the webpage on").Short('h').Default("127.0.0.1").StringVar(&cmd.host)
29+
clause.Flag("port", "The port to serve the webpage on").Default("8080").IntVar(&cmd.port)
30+
31+
command.BindAction(clause, cmd.Run)
32+
}
33+
34+
// Run handles the command with the options as specified in the command.
35+
func (cmd *ServeCommand) Run() error {
36+
fmt.Fprintf(cmd.io.Stdout(), "Serving example app on http://%s:%d\n", cmd.host, cmd.port)
37+
return app.NewServer(cmd.host, cmd.port).Serve()
38+
}

internals/secrethub/account.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package secrethub
22

33
import (
44
"github.com/secrethub/secrethub-cli/internals/cli/ui"
5+
"github.com/secrethub/secrethub-cli/internals/secrethub/command"
56
)
67

78
// AccountCommand handles operations on SecretHub accounts.
@@ -21,7 +22,7 @@ func NewAccountCommand(io ui.IO, newClient newClientFunc, credentialStore Creden
2122
}
2223

2324
// Register registers the command and its sub-commands on the provided Registerer.
24-
func (cmd *AccountCommand) Register(r Registerer) {
25+
func (cmd *AccountCommand) Register(r command.Registerer) {
2526
clause := r.Command("account", "Manage your personal account.")
2627
NewAccountInspectCommand(cmd.io, cmd.newClient).Register(clause)
2728
NewAccountInitCommand(cmd.io, cmd.newClient, cmd.credentialStore).Register(clause)

internals/secrethub/account_email_verify.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/secrethub/secrethub-cli/internals/cli/ui"
7+
"github.com/secrethub/secrethub-cli/internals/secrethub/command"
78
)
89

910
// AccountEmailVerifyCommand is a command to inspect account details.
@@ -21,10 +22,10 @@ func NewAccountEmailVerifyCommand(io ui.IO, newClient newClientFunc) *AccountEma
2122
}
2223

2324
// Register registers the command, arguments and flags on the provided Registerer.
24-
func (cmd *AccountEmailVerifyCommand) Register(r Registerer) {
25+
func (cmd *AccountEmailVerifyCommand) Register(r command.Registerer) {
2526
clause := r.Command("verify-email", "Send an email to the registered email address to prove you own that email address.")
2627

27-
BindAction(clause, cmd.Run)
28+
command.BindAction(clause, cmd.Run)
2829
}
2930

3031
// Run handles the command with the options as specified in the command.

0 commit comments

Comments
 (0)