# Tls Https

> A Claude skill from jkaninda/okapi-skills.

- **Type:** Skill
- **Install:** `agentstack add skill-jkaninda-okapi-skills-tls-https`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [jkaninda](https://agentstack.voostack.com/s/jkaninda)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [jkaninda](https://github.com/jkaninda)
- **Source:** https://github.com/jkaninda/okapi-skills/tree/main/tls_https

## Install

```sh
agentstack add skill-jkaninda-okapi-skills-tls-https
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

## Okapi TLS & HTTPS

### Loading a TLS Config

```go
func okapi.LoadTLSConfig(certFile, keyFile, caFile string, clientAuth bool) (*tls.Config, error)
```

| Parameter | Description |
|-----------|-------------|
| `certFile` | Path to the certificate (PEM) |
| `keyFile` | Path to the private key (PEM) |
| `caFile` | Optional CA certificate for verifying client certs — `""` disables |
| `clientAuth` | Require client certificate verification (mTLS) |

### HTTPS-Only Server

```go
tlsConfig, err := okapi.LoadTLSConfig("cert.pem", "key.pem", "", false)
if err != nil {
    panic(err)
}

o := okapi.New(okapi.WithTLS(tlsConfig), okapi.WithAddr(":8443"))

o.Get("/", func(c *okapi.Context) error {
    return c.OK(okapi.M{"status": "secure"})
})

o.Start() // ListenAndServeTLS
```

When the server's `TLSConfig` is set, `Start()` serves HTTPS on the configured address.

### Dual HTTP + HTTPS

`WithTLSServer` runs a second listener with its own address, sharing the same routes and middleware:

```go
tlsConfig, _ := okapi.LoadTLSConfig("cert.pem", "key.pem", "", false)

o := okapi.Default()                        // HTTP on :8080
o.With(okapi.WithTLSServer(":8443", tlsConfig)) // HTTPS on :8443

o.Start() // HTTP served in a goroutine, HTTPS in the foreground
```

`Stop()` / `StopWithContext(ctx)` gracefully shut down both listeners.

### Mutual TLS (client certificates)

```go
tlsConfig, err := okapi.LoadTLSConfig("server.crt", "server.key", "ca.crt", true)
o := okapi.New(okapi.WithTLS(tlsConfig))
```

With `clientAuth: true`, the CA in `caFile` verifies presented client certificates. Inspect the peer in a handler:

```go
o.Get("/whoami", func(c *okapi.Context) error {
    tls := c.Request().TLS
    if tls == nil || len(tls.PeerCertificates) == 0 {
        return c.AbortUnauthorized("client certificate required")
    }
    return c.OK(okapi.M{"cn": tls.PeerCertificates[0].Subject.CommonName})
})
```

### Custom `*tls.Config` (autocert / Let's Encrypt)

The `*Okapi` struct has no exported fields, so supply a pre-built `*http.Server` instead of assigning to one:

```go
certManager := autocert.Manager{
    Prompt:     autocert.AcceptTOS,
    HostPolicy: autocert.HostWhitelist("example.com", "www.example.com"),
    Cache:      autocert.DirCache("certs"),
}

o := okapi.New(okapi.WithServer(&http.Server{
    Addr:      ":443",
    TLSConfig: certManager.TLSConfig(),
}))

o.Get("/", func(c *okapi.Context) error { return c.OK(okapi.M{"ok": true}) })

// TLSConfig is set, so Start() calls ListenAndServeTLS
go http.ListenAndServe(":80", certManager.HTTPHandler(nil)) // ACME http-01 challenge
o.Start()
```

`okapi.WithTLS(certManager.TLSConfig())` works the same way when you don't need to customise the rest of the server.

### Generating a Development Certificate

```bash
openssl genrsa -out server.key 2048
openssl req -new -x509 -sha256 -key server.key -out server.crt -days 365
```

### HTTP → HTTPS Redirect Middleware

`c.Redirect` writes the redirect and returns nothing, so return `nil` after calling it:

```go
func redirectToHTTPS(c *okapi.Context) error {
    if c.Request().TLS == nil {
        c.Redirect(http.StatusMovedPermanently, "https://"+c.Request().Host+c.Request().RequestURI)
        return nil
    }
    return c.Next()
}

o.Use(redirectToHTTPS)
```

### HSTS

```go
func hsts(c *okapi.Context) error {
    c.SetHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
    return c.Next()
}

o.Use(hsts)
```

### Practices

- Terminate TLS 1.2+ only — set `MinVersion` on a custom `*tls.Config` when you build one yourself.
- Serve HSTS only over HTTPS, and only once you are sure every subdomain supports TLS.
- Keep the ACME http-01 listener on `:80` when using autocert, or use a DNS challenge.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [jkaninda](https://github.com/jkaninda)
- **Source:** [jkaninda/okapi-skills](https://github.com/jkaninda/okapi-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-jkaninda-okapi-skills-tls-https
- Seller: https://agentstack.voostack.com/s/jkaninda
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
