Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ flowchart LR
subscribed agents are notified in the same step. Publishing is idempotent
(unchanged content is a no-op), so only real changes fire a notification.
Git stays the source of truth; the server is the live serving copy.
- `push` / `publish` accept `-tls` and `-ca-cert` for TLS servers.
- `push` / `publish` accept `-tls` for TLS servers. The server certificate is
verified against the system root CAs, or against `-ca-cert <file>` for a
private CA.

## Configuration

Expand Down
22 changes: 22 additions & 0 deletions cmd/promptctl/dial_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

import "testing"

func TestTransportCreds(t *testing.T) {
c, err := transportCreds(false, "")
if err != nil || c.Info().SecurityProtocol != "insecure" {
t.Errorf("no -tls: got %v, %v; want insecure", c, err)
}
// -tls without -ca-cert verifies against the system roots instead of
// failing to open the file "".
c, err = transportCreds(true, "")
if err != nil {
t.Fatalf("-tls without -ca-cert: %v", err)
}
if p := c.Info().SecurityProtocol; p != "tls" {
t.Errorf("-tls without -ca-cert: protocol %q, want tls", p)
}
if _, err := transportCreds(true, "does-not-exist.pem"); err == nil {
t.Error("-tls -ca-cert with a missing file: want an error")
}
}
27 changes: 19 additions & 8 deletions cmd/promptctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ package main

import (
"context"
"crypto/tls"
"errors"
"flag"
"fmt"
Expand Down Expand Up @@ -187,7 +188,7 @@ func pushCmd(args []string) {
fs := flag.NewFlagSet("push", flag.ExitOnError)
server := fs.String("server", "", "after pushing, publish prompts to this live server (host:port)")
useTLS := fs.Bool("tls", false, "use TLS for -server")
caCert := fs.String("ca-cert", "", "CA cert for TLS -server (optional)")
caCert := fs.String("ca-cert", "", "CA cert for TLS -server (default: system roots)")
fs.Parse(args)

validateAll()
Expand All @@ -204,7 +205,7 @@ func publishCmd(args []string) {
fs := flag.NewFlagSet("publish", flag.ExitOnError)
server := fs.String("server", "", "live server address (host:port)")
useTLS := fs.Bool("tls", false, "use TLS")
caCert := fs.String("ca-cert", "", "CA cert for TLS (optional)")
caCert := fs.String("ca-cert", "", "CA cert for TLS (default: system roots)")
fs.Parse(args)
if *server == "" {
log.Fatal("publish needs -server host:port")
Expand Down Expand Up @@ -237,12 +238,9 @@ func publishToServer(server string, useTLS bool, caCert string, paths []string)
}

func dial(addr string, useTLS bool, caCert string) *grpc.ClientConn {
creds := insecure.NewCredentials()
if useTLS {
var err error
if creds, err = credentials.NewClientTLSFromFile(caCert, ""); err != nil {
log.Fatal(err)
}
creds, err := transportCreds(useTLS, caCert)
if err != nil {
log.Fatal(err)
}
conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(creds))
if err != nil {
Expand All @@ -251,6 +249,19 @@ func dial(addr string, useTLS bool, caCert string) *grpc.ClientConn {
return conn
}

// transportCreds picks the gRPC transport: plaintext, TLS verified against the
// system root CAs, or TLS verified against the -ca-cert file.
func transportCreds(useTLS bool, caCert string) (credentials.TransportCredentials, error) {
switch {
case !useTLS:
return insecure.NewCredentials(), nil
case caCert == "":
return credentials.NewTLS(&tls.Config{}), nil // nil RootCAs = system pool
default:
return credentials.NewClientTLSFromFile(caCert, "")
}
}

func authCtx() context.Context {
ctx := context.Background()
if token := os.Getenv("PRIOMPT_TOKEN"); token != "" {
Expand Down
Loading