Auto-generate self-signed certs

This commit is contained in:
IamTheFij 2021-01-07 12:19:56 -05:00
parent 05f700bc93
commit 04dd93c71d
3 changed files with 61 additions and 3 deletions

View File

@ -6,6 +6,10 @@ DIST_TARGETS = $(addprefix dist/$(OUTPUT)-,$(DIST_ARCH))
.PHONY: default
default: slack-status
.PHONY: run
run: slack-status
./slack-status
.PHONY: all
all: dist

View File

@ -2,6 +2,14 @@
Set your Slack status via the command line
## Requirements
Rather than host a web server that you would need to trust, this command runs one on your local machine to retrieve the OAuth code. This page is hosted with an auto generated, self-signed certificate.
This requires you to have `openssl` installed on your machine and, when the page loads for the first time, it will require you to trust the certificate or ignore the warning.
Here's how to do that on [Firefox](https://support.mozilla.org/en-US/kb/error-codes-secure-websites?as=u&utm_source=inproduct#w_self-signed-certificate). On Chrome, you may have to enable `chrome://flags/#allow-insecure-localhost`.
## Example usage
Set auth token (it will store it in `~/.config/slack-status-cli` or your `$XDG_CONFIG_HOME` dir

52
auth.go
View File

@ -7,7 +7,9 @@ import (
"log"
"net/http"
"os"
"os/exec"
"strings"
"time"
"github.com/slack-go/slack"
)
@ -51,7 +53,12 @@ func (app slackApp) listenForCode() (string, error) {
var code string
// Also, should generate TLS certificate to use since https is a required scheme
server := http.Server{Addr: app.listenHost}
server := http.Server{
Addr: app.listenHost,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
}
http.HandleFunc(app.listenPath, func(w http.ResponseWriter, r *http.Request) {
codes := r.URL.Query()["code"]
@ -71,25 +78,64 @@ func (app slackApp) listenForCode() (string, error) {
}()
})
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
certPath := getConfigFilePath("cert.pem")
keyPath := getConfigFilePath("key.pem")
if !fileExists(certPath) || !fileExists(keyPath) {
if err := generateSelfSignedCertificates(certPath, keyPath); err != nil {
return "", err
}
}
if err := server.ListenAndServeTLS(certPath, keyPath); err != nil && !errors.Is(err, http.ErrServerClosed) {
return "", err
}
return code, nil
}
func fileExists(path string) bool {
if _, err := os.Stat(path); os.IsNotExist(err) {
return false
}
return true
}
func generateSelfSignedCertificates(certPath, keyPath string) error {
command := exec.Command(
"openssl",
"req",
"-x509",
"-subj",
"/C=US/O=Slack Status CLI/CN=localhost:8888",
"-nodes",
"-days",
"365",
"-newkey",
"rsa:2048",
"-keyout",
keyPath,
"-out",
certPath,
)
return command.Run()
}
func authenticate() (string, error) {
app := slackApp{
userScopes: []string{"dnd:write", "users.profile:write"},
scopes: []string{"dnd:write", "users.profile:write"},
clientID: getEnvOrDefault("CLIENT_ID", defaultClientID),
clientSecret: getEnvOrDefault("CLIENT_SECRET", defaultClientSecret),
redirectURI: "http://localhost:8888/auth",
redirectURI: "https://localhost:8888/auth",
listenHost: "localhost:8888",
listenPath: "/auth",
}
fmt.Println("To authenticate, go to the following URL:")
fmt.Println("NOTE: After you authenticate with Slack, it will redirect you to a server running on your local computer. Your browser will present a security error because it cann't verify the server. You will need to manually add an exception or tell your browser to proceed anyway.")
fmt.Println(app.getAuthURL())
code, err := app.listenForCode()