Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support HTTPS for Manager API #1824

Merged
merged 9 commits into from
Apr 29, 2021
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
6 changes: 0 additions & 6 deletions .github/workflows/test-frontend-multiple-node-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,9 @@ on:
push:
branches:
- master
paths-ignore:
- 'docs/**'
- 'api/**'
pull_request:
branches:
- master
paths-ignore:
- 'docs/**'
- 'api/**'

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
Expand Down
29 changes: 29 additions & 0 deletions api/cmd/managerapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ package cmd

import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
"time"

Expand All @@ -48,6 +51,9 @@ func printInfo() {
fmt.Fprint(os.Stdout, "The manager-api is running successfully!\n\n")
printVersion()
fmt.Fprintf(os.Stdout, "%-8s: %s:%d\n", "Listen", conf.ServerHost, conf.ServerPort)
if conf.SSLCert != "" && conf.SSLKey != "" {
fmt.Fprintf(os.Stdout, "%-8s: %s:%d\n", "HTTPS Listen", conf.SSLHost, conf.SSLPort)
}
fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Loglevel", conf.ErrorLogLevel)
fmt.Fprintf(os.Stdout, "%-8s: %s\n\n", "Logfile", conf.ErrorLogPath)
}
Expand Down Expand Up @@ -124,6 +130,29 @@ func NewManagerAPICommand() *cobra.Command {
}
}()

// HTTPS
if conf.SSLCert != "" && conf.SSLKey != "" {
addrSSL := net.JoinHostPort(conf.ServerHost, strconv.Itoa(conf.SSLPort))
serverSSL := &http.Server{
Addr: addrSSL,
Handler: r,
ReadTimeout: time.Duration(1000) * time.Millisecond,
WriteTimeout: time.Duration(5000) * time.Millisecond,
TLSConfig: &tls.Config{
// Causes servers to use Go's default ciphersuite preferences,
// which are tuned to avoid attacks. Does nothing on clients.
PreferServerCipherSuites: true,
},
}
go func() {
err := serverSSL.ListenAndServeTLS(conf.SSLCert, conf.SSLKey)
if err != nil && err != http.ErrServerClosed {
utils.CloseAll()
log.Fatalf("listen and serve for HTTPS failed: %s", err)
}
}()
}

printInfo()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to update the printInfo.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated.


sig := <-quit
Expand Down
11 changes: 10 additions & 1 deletion api/conf/conf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,21 @@
# limitations under the License.
#

# yamllint disable rule:comments-indentation
conf:
listen: # yamllint disable rule:comments-indentation
gxthrj marked this conversation as resolved.
Show resolved Hide resolved
listen:
# host: 127.0.0.1 # the address on which the `Manager API` should listen.
# The default value is 0.0.0.0, if want to specify, please enable it.
# This value accepts IPv4, IPv6, and hostname.
port: 9000 # The port on which the `Manager API` should listen.

# ssl:
# host: 127.0.0.1 # the address on which the `Manager API` should listen for HTTPS.
# The default value is 0.0.0.0, if want to specify, please enable it.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may also support the mTLS.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure. we may support mTLS in the future.

# port: 9001 # The port on which the `Manager API` should listen for HTTPS.
# cert: "/tmp/cert/example.crt" # Path of your SSL cert.
# key: "/tmp/cert/example.key" # Path of your SSL key.

allow_list: # If we don't set any IP list, then any IP access is allowed by default.
- 127.0.0.1 # The rules are checked in sequence until the first match is found.
- ::1 # In this example, access is allowed only for IPv4 network 127.0.0.1, and for IPv6 network ::1.
Expand Down
24 changes: 23 additions & 1 deletion api/internal/conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ var (
WorkDir = "."
ServerHost = "0.0.0.0"
ServerPort = 80
SSLHost = "0.0.0.0"
SSLPort = 443
SSLCert string
SSLKey string
ETCDConfig *Etcd
ErrorLogLevel = "warn"
ErrorLogPath = "logs/error.log"
Expand Down Expand Up @@ -73,6 +77,13 @@ type Etcd struct {
Prefix string
}

type SSL struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Cert string `yaml:"cert"`
Key string `yaml:"key"`
}

type Listen struct {
Host string
Port int
Expand All @@ -95,6 +106,7 @@ type Log struct {
type Conf struct {
Etcd Etcd
Listen Listen
SSL SSL
Log Log
AllowList []string `yaml:"allow_list"`
MaxCpu int `yaml:"max_cpu"`
Expand Down Expand Up @@ -152,11 +164,21 @@ func setConf() {
if config.Conf.Listen.Port != 0 {
ServerPort = config.Conf.Listen.Port
}

if config.Conf.Listen.Host != "" {
ServerHost = config.Conf.Listen.Host
}

// SSL
if config.Conf.SSL.Port != 0 {
SSLPort = config.Conf.SSL.Port
}
if config.Conf.SSL.Cert != "" {
SSLCert = config.Conf.SSL.Cert
}
if config.Conf.SSL.Key != "" {
SSLKey = config.Conf.SSL.Key
}

// for etcd
if len(config.Conf.Etcd.Endpoints) > 0 {
initEtcdConfig(config.Conf.Etcd)
Expand Down
29 changes: 29 additions & 0 deletions api/test/shell/cli_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,35 @@ sleep 6
clean_up


# HTTPS test
currentDir=$(pwd)
if [[ $KERNEL = "Darwin" ]]; then
sed -i "" 's@# ssl:@ssl:@' conf/conf.yaml
sed -i "" 's@# port: 9001@ port: 9001@' conf/conf.yaml
sed -i "" "s@# cert: \"/tmp/cert/example.crt\"@ cert: \"$currentDir/test/certs/test2.crt\"@" conf/conf.yaml
sed -i "" "s@# key: \"/tmp/cert/example.key\"@ cert: \"$currentDir/test/certs/test2.key\"@" conf/conf.yaml
else
sed -i 's@# ssl:@ssl:@' conf/conf.yaml
sed -i 's@# port: 9001@ port: 9001@' conf/conf.yaml
sed -i "s@# cert: \"/tmp/cert/example.crt\"@ cert: \"$currentDir/test/certs/test2.crt\"@" conf/conf.yaml
sed -i "s@# key: \"/tmp/cert/example.key\"@ key: \"$currentDir/test/certs/test2.key\"@" conf/conf.yaml
fi

./manager-api &
sleep 3

# access by HTTPS
code=$(curl -k -i -m 20 -o /dev/null -s -w %{http_code} --resolve 'www.test2.com:9001:127.0.0.1' https://www.test2.com:9001/apisix/admin/tool/version)
if [ ! $code -eq 200 ]; then
echo "failed: verify HTTPS failed"
exit 1
fi

./manager-api stop
sleep 6
clean_up


# etcd basic auth
# add root user
curl -L http://localhost:2379/v3/auth/user/add -d '{"name": "root", "password": "root"}'
Expand Down