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(service): switch from http to https #56

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
74329d4
fix(cli): consolidate and repair backend error handling
scott-howe-1 Nov 21, 2024
ebeea1a
fix(cli): Remove unnecessary log message.
scott-howe-1 Nov 21, 2024
43fcc13
docs(cli): add function description
scott-howe-1 Nov 21, 2024
b440888
feat(service): switch to using https (remove http)
scott-howe-1 Nov 21, 2024
6231ad2
feat(cli): add https support
scott-howe-1 Nov 21, 2024
528489f
Merge branch 'main' into feat/service-switch-to-https
scott-howe-1 Nov 22, 2024
e7822f5
Merge commit '211a099d878427fd0fbcc1089130285cbc1a34a5' into feat/ser…
scott-howe-1 Dec 2, 2024
2788573
fix(service): fix device discovery error handling during service star…
scott-howe-1 Dec 4, 2024
f6d7c55
refactor(cli): command usage and example string generation refactor a…
scott-howe-1 Dec 4, 2024
cd1aceb
Merge branch 'main' into feat/service-switch-to-https
scott-howe-1 Dec 4, 2024
5c63d28
feat(webui): device discovery in cfm webui (#58)
Meng-20 Dec 6, 2024
5a6dc7e
fix(docker): update the docker running command to make D-bus availabl…
Meng-20 Dec 6, 2024
4faa226
fix(service): fix error handling bugs during add blade\host (#61)
scott-howe-1 Dec 6, 2024
e35f12f
Merge branch 'main' into feat/service-switch-to-https
scott-howe-1 Dec 6, 2024
701d222
Merge branch 'main' into feat/service-switch-to-https
scott-howe-1 Dec 10, 2024
1b634df
Merge branch 'main' into feat/service-switch-to-https
scott-howe-1 Dec 11, 2024
22a3312
Merge branch 'main' into feat/service-switch-to-https
scott-howe-1 Dec 17, 2024
f194f8d
Merge branch 'main' into feat/service-switch-to-https
scott-howe-1 Dec 18, 2024
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
Prev Previous commit
Next Next commit
feat(service): switch to using https (remove http)
The service provide a self-signed certificate file (.crt) so clients can use secure.  Insecure is also available.
  • Loading branch information
scott-howe-1 committed Nov 21, 2024
commit b440888a6c30f4108a796c8e9030f52fe9c490b5
57 changes: 56 additions & 1 deletion cmd/cfm-service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ package main

import (
"context"
"crypto/tls"
"fmt"
"log"
"net/http"
"os"
"os/exec"
"strings"
"sync"

Expand All @@ -16,6 +18,7 @@ import (
"cfm/pkg/common/datastore"
"cfm/pkg/openapi"
"cfm/pkg/redfishapi"
"cfm/pkg/security"
"cfm/services"

"github.com/rs/cors"
Expand Down Expand Up @@ -88,7 +91,59 @@ func main() {
}
}

server, err := GenerateCfmServer(ctx, &settings, &handler)
if err != nil {
logger.Error(err, ", failed to generate cfm server: %s", err)
os.Exit(1)
}

// Start the main service
logger.V(0).Info("cfm-service web server", "port", settings.Port)
log.Fatal(http.ListenAndServe(":"+settings.Port, handler))
log.Fatal(server.ListenAndServeTLS("", ""))
}

// GenerateCfmServer - Generates the primary cfm server using a runtine-generated self-signed certificate.
// Updates environmenetal variable SEAGATE_CFM_SERVICE_CRT_PATH.
// Saves the certificate to the SEAGATE_CFM_SERVICE_CRT_PATH location so that it can be shared with a local client.
func GenerateCfmServer(ctx context.Context, settings *common.Settings, handler *http.Handler) (*http.Server, error) {
logger := klog.FromContext(ctx)

// Set environment variable (visible to webui but not cli (runs in different shell))
err := os.Setenv("SEAGATE_CFM_SERVICE_CRT_PATH", security.SEAGATE_CFM_SERVICE_CRT_FILEPATH)
if err != nil {
return nil, fmt.Errorf("failure: setting environment variable: %v", err)
}

// Generate the keys
cert, certPEM, err := security.GenerateSelfSignedCert()
if err != nil {
return nil, fmt.Errorf("failure: tls (self-signed) certificate generation: %v", err)
}

// Write the certificate to a file
err = os.WriteFile(security.SEAGATE_CFM_SERVICE_CRT_FILEPATH, []byte(certPEM), 0644)
if err != nil {
return nil, fmt.Errorf("failure: tls cert file save: %v", err)
}

logger.V(2).Info(fmt.Sprintf("cfm tls (self-signed) cert file saved to: %s ", security.SEAGATE_CFM_SERVICE_CRT_FILEPATH))

// Update CA certificates
cmd := exec.Command("update-ca-certificates") // This assumes the above self-signed .crt file is written to the correct location
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("failure: update CA certificates: %v", err)
}

// Configure the server
server := &http.Server{
Addr: ":" + settings.Port,
TLSConfig: &tls.Config{
Certificates: []tls.Certificate{*cert},
},
Handler: *handler,
}

return server, nil
}
7 changes: 5 additions & 2 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ RUN git apply api/patch/*.redfish.patch
# build the excutable
RUN make build-go

FROM node:alpine as npm
FROM node:alpine AS npm
ENV BASEPATH=/cfm

# copy source code with generated files to go image
Expand All @@ -60,14 +60,17 @@ RUN npm run build
FROM alpine:latest
ENV BASEPATH=/cfm

# Install packages
RUN apk add --no-cache ca-certificates openssl bash curl jq

# copy source code with generated files to go image
COPY --from=go ${BASEPATH}/cfm-service ${BASEPATH}/cfm-service
COPY --from=go ${BASEPATH}/cfm-cli ${BASEPATH}/cfm-cli
COPY --from=npm ${BASEPATH}/webui/dist ${BASEPATH}/webui/dist

RUN ln -s /local/cfmdatastore.json ${BASEPATH}/cfmdatastore.json

LABEL org.opencontainers.image.source https://github.com/seagate/cfm
LABEL org.opencontainers.image.source=https://github.com/seagate/cfm

WORKDIR ${BASEPATH}
# Start the service
Expand Down
74 changes: 74 additions & 0 deletions pkg/security/certificates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
package security

import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"net"
"time"
)

const (
SEAGATE_CFM_SERVICE_CRT_FILEPATH = "/usr/local/share/ca-certificates/github_com_seagate_cfm-self-signed.crt"
)

// GenerateSelfSignedCert - Generates the self-signed SSL/TLS certificate and private key at runtime.
func GenerateSelfSignedCert() (*tls.Certificate, []byte, error) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, nil, err
}

notBefore := time.Now()
notAfter := notBefore.Add(365 * 24 * time.Hour)

serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
if err != nil {
return nil, nil, err
}

template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Country: []string{"US"},
Organization: []string{"SEAGATE TECHNOLOGY LLC"},
OrganizationalUnit: []string{"MAG"},
Locality: []string{"Longmont"},
Province: []string{"Colorado"},
CommonName: "localhost", // Set CommonName to a valid hostname
},
NotBefore: notBefore,
NotAfter: notAfter,

KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, // Add IP SAN
}

derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
return nil, nil, err
}

certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
keyPEM, err := x509.MarshalECPrivateKey(priv)
if err != nil {
return nil, nil, err
}

keyPEMBytes := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyPEM})

cert, err := tls.X509KeyPair(certPEM, keyPEMBytes)
if err != nil {
return nil, nil, err
}

return &cert, certPEM, nil
}