Added env based support for HTTPS connection (#4706)

* Added env based support for HTTPS connection

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* resolved review comments

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* updated logic

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* fixed importd

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* added helper files

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* resolved comments

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* resolved comments

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* Update push.yml

* minor changes

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* minor changes

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* minor changes

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* minor changes

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* minor changes

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* Update push.yml

* updated oush.yam

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* updated manifest

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

---------

Signed-off-by: Saranya-jena <saranya.jena@harness.io>
Co-authored-by: Namkyu Park <53862866+namkyu1999@users.noreply.github.com>
This commit is contained in:
Saranya Jena 2024-07-08 13:59:43 +05:30 committed by GitHub
parent a00691fe8b
commit 9f4fe2598b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 359 additions and 5 deletions

View File

@ -4,11 +4,13 @@ import (
"flag"
"fmt"
"net"
"net/http"
"runtime"
"time"
response "github.com/litmuschaos/litmus/chaoscenter/authentication/api/handlers"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/authConfig"
"google.golang.org/grpc/credentials"
grpcHandler "github.com/litmuschaos/litmus/chaoscenter/authentication/api/handlers/grpc"
"github.com/litmuschaos/litmus/chaoscenter/authentication/api/middleware"
@ -132,6 +134,14 @@ func main() {
validatedAdminSetup(applicationService)
go runGrpcServer(applicationService)
if utils.EnableInternalTls {
if utils.CustomTlsCertPath != "" && utils.TlSKeyPath != "" {
go runGrpcServerWithTLS(applicationService)
} else {
log.Fatalf("Failure to start chaoscenter authentication GRPC server due to empty TLS cert file path and TLS key path")
}
}
runRestServer(applicationService)
}
@ -186,6 +196,29 @@ func runRestServer(applicationService services.ApplicationService) {
routes.ProjectRouter(app, applicationService)
log.Infof("Listening and serving HTTP on %s", utils.Port)
if utils.EnableInternalTls {
log.Infof("Listening and serving HTTPS on %s", utils.PortHttps)
if utils.CustomTlsCertPath != "" && utils.TlSKeyPath != "" {
conf := utils.GetTlsConfig()
server := http.Server{
Addr: utils.PortHttps,
Handler: app,
TLSConfig: conf,
}
log.Infof("Listening and serving HTTPS on %s", utils.Port)
go func() {
err := server.ListenAndServeTLS("", "")
if err != nil {
log.Fatalf("Failure to start litmus-portal authentication REST server due to %v", err)
}
}()
} else {
log.Fatalf("Failure to start chaoscenter authentication REST server due to empty TLS cert file path and TLS key path")
}
}
err := app.Run(utils.Port)
if err != nil {
log.Fatalf("Failure to start litmus-portal authentication REST server due to %v", err)
@ -205,6 +238,34 @@ func runGrpcServer(applicationService services.ApplicationService) {
log.Infof("Listening and serving gRPC on %s", utils.GrpcPort)
err = grpcServer.Serve(lis)
if err != nil {
log.Fatalf("Failure to start litmus-portal authentication GRPC server due to %v", err)
log.Fatalf("Failure to start chaoscenter authentication GRPC server due to %v", err)
}
}
func runGrpcServerWithTLS(applicationService services.ApplicationService) {
// Starting gRPC server
lis, err := net.Listen("tcp", utils.GrpcPortHttps)
if err != nil {
log.Fatalf("Failure to start litmus-portal authentication server due to %s", err)
}
// configuring TLS config based on provided certificates & keys
conf := utils.GetTlsConfig()
// create tls credentials
tlsCredentials := credentials.NewTLS(conf)
// create grpc server with tls credential
grpcServer := grpc.NewServer(grpc.Creds(tlsCredentials))
grpcApplicationServer := grpcHandler.ServerGrpc{ApplicationService: applicationService}
grpcPresenter.RegisterAuthRpcServiceServer(grpcServer, &grpcApplicationServer)
log.Infof("Listening and serving gRPC on %s with TLS", utils.GrpcPort)
err = grpcServer.Serve(lis)
if err != nil {
log.Fatalf("Failure to start chaoscenter authentication GRPC server due to %v", err)
}
}

View File

@ -1,8 +1,12 @@
package utils
import (
"crypto/tls"
"crypto/x509"
"os"
"strconv"
log "github.com/sirupsen/logrus"
)
var (
@ -20,9 +24,15 @@ var (
DexClientID = os.Getenv("DEX_OAUTH_CLIENT_ID")
DexClientSecret = os.Getenv("DEX_OAUTH_CLIENT_SECRET")
DexOIDCIssuer = os.Getenv("OIDC_ISSUER")
EnableInternalTls = getEnvAsBool("ENABLE_INTERNAL_TLS", false)
CustomTlsCertPath = os.Getenv("CUSTOM_TLS_CERT_PATH")
TlSKeyPath = os.Getenv("TLS_KEY_PATH")
CaCertPath = os.Getenv("CA_CERT_PATH")
DBName = "auth"
Port = ":3000"
PortHttps = ":3001"
GrpcPort = ":3030"
GrpcPortHttps = ":3031"
UserCollection = "users"
ProjectCollection = "project"
AuthConfigCollection = "auth-config"
@ -33,6 +43,7 @@ var (
PasswordEncryptionCost = 15
DefaultLitmusGqlGrpcEndpoint = "localhost"
DefaultLitmusGqlGrpcPort = ":8000"
//DefaultLitmusGqlGrpcPortHttps = ":8001" // enable when in use
)
func getEnvAsInt(name string, defaultVal int) int {
@ -50,3 +61,32 @@ func getEnvAsBool(name string, defaultVal bool) bool {
}
return defaultVal
}
func GetTlsConfig() *tls.Config {
// read ca's cert, verify to client's certificate
caPem, err := os.ReadFile(CaCertPath)
if err != nil {
log.Fatal(err)
}
// create cert pool and append ca's cert
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(caPem) {
log.Fatal(err)
}
// read server cert & key
serverCert, err := tls.LoadX509KeyPair(CustomTlsCertPath, TlSKeyPath)
if err != nil {
log.Fatal(err)
}
// configuring TLS config based on provided certificates & keys to
conf := &tls.Config{
Certificates: []tls.Certificate{serverCert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: certPool,
}
return conf
}

View File

@ -0,0 +1 @@
subjectAltName=DNS:*.someclient.com,IP:0.0.0.0,DNS:localhost

View File

@ -5,6 +5,7 @@ import (
"errors"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/grpc"
"github.com/sirupsen/logrus"
grpc2 "google.golang.org/grpc"
)
@ -20,7 +21,8 @@ func ValidateRole(ctx context.Context, projectID string,
requiredRoles,
invitation)
if err != nil {
return errors.New("permission_denied")
logrus.Error(err)
return errors.New("permission_denied: " + err.Error())
}
return nil
}

View File

@ -3,6 +3,9 @@ package grpc
import (
"context"
"errors"
"strconv"
"google.golang.org/grpc/credentials"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/protos"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/utils"
@ -13,10 +16,34 @@ import (
// GetAuthGRPCSvcClient returns an RPC client for Authentication service
func GetAuthGRPCSvcClient(conn *grpc.ClientConn) (protos.AuthRpcServiceClient, *grpc.ClientConn) {
conn, err := grpc.Dial(utils.Config.LitmusAuthGrpcEndpoint+utils.Config.LitmusAuthGrpcPort, grpc.WithBlock(), grpc.WithInsecure())
enableHTTPSConnection, err := strconv.ParseBool(utils.Config.EnableInternalTls)
if err != nil {
logrus.Fatalf("did not connect: %s", err)
logrus.Errorf("unable to parse boolean value %v", err)
}
if enableHTTPSConnection {
if utils.Config.ServerTlsCertPath != "" {
// configuring TLS config based on provided certificates & keys
conf := utils.GetTlsConfig(utils.Config.ClientTlsCertPath, utils.Config.ClientTlsKeyPath, false)
tlsCredential := credentials.NewTLS(conf)
// Set up a connection to the server.
conn, err = grpc.NewClient(utils.Config.LitmusAuthGrpcEndpoint+utils.Config.LitmusAuthGrpcPortHttps, grpc.WithTransportCredentials(tlsCredential))
if err != nil {
logrus.Fatalf("did not connect: %v", err)
}
} else {
logrus.Fatalf("Failure to start chaoscenter authentication REST server due to empty TLS cert file path and TLS key path")
}
} else {
conn, err = grpc.Dial(utils.Config.LitmusAuthGrpcEndpoint+utils.Config.LitmusAuthGrpcPort, grpc.WithBlock(), grpc.WithInsecure())
if err != nil {
logrus.Fatalf("did not connect: %s", err)
}
}
return protos.NewAuthRpcServiceClient(conn), conn
}

View File

@ -4,6 +4,8 @@ import (
"regexp"
"strconv"
"google.golang.org/grpc/credentials"
"github.com/gin-gonic/gin"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/api/middleware"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/chaoshub"
@ -35,6 +37,7 @@ import (
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/config"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/handlers"
pb "github.com/litmuschaos/litmus/chaoscenter/graphql/server/protos"
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
)
@ -100,7 +103,20 @@ func main() {
if err := validateVersion(); err != nil {
log.Fatal(err)
}
enableHTTPSConnection, err := strconv.ParseBool(utils.Config.EnableInternalTls)
if err != nil {
logrus.Errorf("unable to parse boolean value %v", err)
}
go startGRPCServer(utils.Config.RpcPort, mongodbOperator) // start GRPC serve
if enableHTTPSConnection {
if utils.Config.ServerTlsCertPath != "" && utils.Config.ServerTlsKeyPath != "" {
go startGRPCServerWithTLS(mongodbOperator) // start GRPC serve
} else {
log.Fatalf("Failure to start chaoscenter authentication REST server due to empty TLS cert file path and TLS key path")
}
}
srv := handler.New(generated.NewExecutableSchema(graph.NewConfig(mongodbOperator)))
srv.AddTransport(transport.POST{})
@ -152,8 +168,24 @@ func main() {
projectEventChannel := make(chan string)
go projects.ProjectEvents(projectEventChannel, mongodb.MgoClient, mongodbOperator)
log.Infof("chaos manager running at http://localhost:%s", utils.Config.HttpPort)
if enableHTTPSConnection {
log.Infof("graphql server running at https://localhost:%s", utils.Config.HttpsPort)
// configuring TLS config based on provided certificates & keys
conf := utils.GetTlsConfig(utils.Config.ServerTlsCertPath, utils.Config.ServerTlsKeyPath, true)
server := http.Server{
Addr: ":" + utils.Config.HttpsPort,
Handler: router,
TLSConfig: conf,
}
if utils.Config.ServerTlsCertPath != "" && utils.Config.ServerTlsKeyPath != "" {
go log.Fatal(server.ListenAndServeTLS("", ""))
}
}
log.Infof("graphql server running at http://localhost:%s", utils.Config.HttpPort)
log.Fatal(http.ListenAndServe(":"+utils.Config.HttpPort, router))
}
// startGRPCServer initializes, registers services to and starts the gRPC server for RPC calls
@ -172,3 +204,28 @@ func startGRPCServer(port string, mongodbOperator mongodb.MongoOperator) {
log.Infof("GRPC server listening on %v", lis.Addr())
log.Fatal(grpcServer.Serve(lis))
}
// startGRPCServerWithTLS initializes, registers services to and starts the gRPC server for RPC calls
func startGRPCServerWithTLS(mongodbOperator mongodb.MongoOperator) {
lis, err := net.Listen("tcp", ":"+utils.Config.RpcPortHttps)
if err != nil {
log.Fatal("failed to listen: %w", err)
}
// configuring TLS config based on provided certificates & keys
conf := utils.GetTlsConfig(utils.Config.ServerTlsCertPath, utils.Config.ServerTlsKeyPath, true)
// create tls credentials
tlsCredentials := credentials.NewTLS(conf)
// create grpc server with tls credential
grpcServer := grpc.NewServer(grpc.Creds(tlsCredentials))
// Register services
pb.RegisterProjectServer(grpcServer, &projects.ProjectServer{Operator: mongodbOperator})
log.Infof("GRPC server listening on %v", lis.Addr())
log.Fatal(grpcServer.Serve(lis))
}

View File

@ -0,0 +1,47 @@
package utils
import (
"crypto/tls"
"crypto/x509"
"os"
log "github.com/sirupsen/logrus"
)
func GetTlsConfig(certPath string, keyPath string, isServerConfig bool) *tls.Config {
// read ca's cert, verify to client's certificate
caPem, err := os.ReadFile(Config.CaCertPath)
if err != nil {
log.Fatal(err)
}
// create cert pool and append ca's cert
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(caPem) {
log.Fatal(err)
}
// read server cert & key
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil {
log.Fatal(err)
}
config := &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: certPool,
}
if isServerConfig {
// configuring TLS config based on provided certificates & keys to
conf := &tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: certPool,
}
return conf
}
return config
}

View File

@ -23,17 +23,26 @@ type Configuration struct {
TlsCertB64 string `split_words:"true"`
LitmusAuthGrpcEndpoint string `split_words:"true" default:"localhost"`
LitmusAuthGrpcPort string `split_words:"true" default:":3030"`
LitmusAuthGrpcPortHttps string `split_words:"true" default:":3031"`
KubeConfigFilePath string `split_words:"true"`
RemoteHubMaxSize string `split_words:"true"`
SkipSslVerify string `split_words:"true"`
HttpPort string `split_words:"true" default:"8080"`
HttpsPort string `split_words:"true" default:"8081"`
RpcPort string `split_words:"true" default:"8000"`
RpcPortHttps string `split_words:"true" default:"8001"`
InfraCompatibleVersions string `required:"true" split_words:"true"`
DefaultHubGitURL string `required:"true" default:"https://github.com/litmuschaos/chaos-charts"`
DefaultHubBranchName string `required:"true" split_words:"true"`
CustomChaosHubPath string `split_words:"true" default:"/tmp/"`
DefaultChaosHubPath string `split_words:"true" default:"/tmp/default/"`
EnableGQLIntrospection string `split_words:"true" default:"false"`
EnableInternalTls string `split_words:"true" default:"false"`
ServerTlsCertPath string `split_words:"true"`
ServerTlsKeyPath string `split_words:"true"`
ClientTlsCertPath string `split_words:"true"`
ClientTlsKeyPath string `split_words:"true"`
CaCertPath string `split_words:"true"`
AllowedOrigins []string `split_words:"true" default:"^(http://|https://|)litmuschaos.io(:[0-9]+|)?,^(http://|https://|)localhost(:[0-9]+|)"`
}

View File

@ -245,9 +245,23 @@ spec:
value: '["ci"]'
- name: ALLOWED_ORIGINS
value: ".*"
- name: ENABLE_INTERNAL_TLS
value: "false"
- name: SERVER_TLS_CERT_PATH
value: ""
- name: SERVER_TLS_KEY_PATH
value: ""
- name: CLIENT_TLS_CERT_PATH
value: ""
- name: CLIENT_KEY_CERT_PATH
value: ""
- name: CA_CERT_PATH
value: ""
ports:
- containerPort: 8080
- containerPort: 8000
- containerPort: 8081
- containerPort: 8001
imagePullPolicy: Always
resources:
requests:
@ -272,6 +286,12 @@ spec:
- name: graphql-rpc-server
port: 8000
targetPort: 8000
- name: graphql-server-https
port: 9004
targetPort: 8081
- name: graphql-rpc-server-https
port: 8001
targetPort: 8001
selector:
component: litmusportal-server
---
@ -318,9 +338,19 @@ spec:
value: ":8000"
- name: ALLOWED_ORIGINS
value: ".*"
- name: ENABLE_INTERNAL_TLS
value: "false"
- name: CUSTOM_TLS_CERT_PATH
value: ""
- name: TLS_KEY_PATH
value: ""
- name: CA_CERT_PATH
value: ""
ports:
- containerPort: 3000
- containerPort: 3030
- containerPort: 3001
- containerPort: 3031
imagePullPolicy: Always
resources:
requests:
@ -345,5 +375,11 @@ spec:
- name: auth-rpc-server
port: 3030
targetPort: 3030
- name: auth-server-https
port: 9005
targetPort: 3001
- name: auth-rpc-server-https
port: 3031
targetPort: 3031
selector:
component: litmusportal-auth-server

View File

@ -229,9 +229,23 @@ spec:
value: '["ci"]'
- name: ALLOWED_ORIGINS
value: ".*"
- name: ENABLE_INTERNAL_TLS
value: "false"
- name: SERVER_TLS_CERT_PATH
value: ""
- name: SERVER_TLS_KEY_PATH
value: ""
- name: CLIENT_TLS_CERT_PATH
value: ""
- name: CLIENT_KEY_CERT_PATH
value: ""
- name: CA_CERT_PATH
value: ""
ports:
- containerPort: 8080
- containerPort: 8000
- containerPort: 8081
- containerPort: 8001
imagePullPolicy: Always
---
apiVersion: v1
@ -247,6 +261,12 @@ spec:
- name: graphql-rpc-server
port: 8000
targetPort: 8000
- name: graphql-server-https
port: 9004
targetPort: 8081
- name: graphql-rpc-server-https
port: 8001
targetPort: 8001
selector:
component: litmusportal-server
---
@ -293,9 +313,19 @@ spec:
value: ":8000"
- name: ALLOWED_ORIGINS
value: ".*"
- name: ENABLE_INTERNAL_TLS
value: "false"
- name: CUSTOM_TLS_CERT_PATH
value: ""
- name: TLS_KEY_PATH
value: ""
- name: CA_CERT_PATH
value: ""
ports:
- containerPort: 3000
- containerPort: 3030
- containerPort: 3001
- containerPort: 3031
imagePullPolicy: Always
---
apiVersion: v1
@ -311,5 +341,11 @@ spec:
- name: auth-rpc-server
port: 3030
targetPort: 3030
- name: auth-server-https
port: 9005
targetPort: 3001
- name: auth-rpc-server-https
port: 3031
targetPort: 3031
selector:
component: litmusportal-auth-server

View File

@ -0,0 +1,37 @@
# delete pem file
rm *.pem
# Create CA private key and self-signed certificate
# adding -nodes to not encrypt the private key
openssl req -x509 -newkey rsa:4096 -nodes -days 365 -keyout ca-key.pem -out ca-cert.pem -subj "/C=TR/ST=ASIA/L=ISTANBUL/O=DEV/OU=TUTORIAL/CN=*.litmuschaos.io/emailAddress=litmuschaos@gmail.com"
echo "CA's self-signed certificate"
openssl x509 -in ca-cert.pem -noout -text
# Create Web Server private key and CSR
# adding -nodes to not encrypt the private key
openssl req -newkey rsa:4096 -nodes -keyout server-key.pem -out server-req.pem -subj "/C=TR/ST=ASIA/L=ISTANBUL/O=DEV/OU=BLOG/CN=*.litmuschaos.io/emailAddress=litmuschaos@gmail.com"
# Sign the Web Server Certificate Request (CSR)
openssl x509 -req -in server-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile server-ext.conf
echo "Server's signed certificate"
openssl x509 -in server-cert.pem -noout -text
# Verify certificate
echo "Verifying certificate"
openssl verify -CAfile ca-cert.pem server-cert.pem
# Generate client's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -keyout client-key.pem -out client-req.pem -subj "/C=TR/ST=EUROPE/L=ISTANBUL/O=DEV/OU=CLIENT/CN=*.litmuschaos.io/emailAddress=litmuschaos@gmail.com"
# Sign the Client Certificate Request (CSR)
openssl x509 -req -in client-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile client-ext.conf
echo "Client's signed certificate"
openssl x509 -in client-cert.pem -noout -text

View File

@ -0,0 +1 @@
subjectAltName=DNS:*.litmuschaos.io,IP:0.0.0.0,DNS:localhost