Skip to content

Commit

Permalink
changes to onboarding token to include role in body
Browse files Browse the repository at this point in the history
Signed-off-by: Rewant Soni <resoni@redhat.com>
  • Loading branch information
rewantsoni committed Jul 19, 2024
1 parent 0f3202c commit a3b7ebd
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 14 deletions.
3 changes: 2 additions & 1 deletion controllers/storagecluster/storageclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
ocsclientv1a1 "github.com/red-hat-storage/ocs-client-operator/api/v1alpha1"
ocsv1 "github.com/red-hat-storage/ocs-operator/api/v4/v1"
"github.com/red-hat-storage/ocs-operator/v4/controllers/util"
"github.com/red-hat-storage/ocs-operator/v4/services"
kerrors "k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
Expand All @@ -31,7 +32,7 @@ func (s *storageClient) ensureCreated(r *StorageClusterReconciler, storagecluste
storageClient.Name = storagecluster.Name
_, err := controllerutil.CreateOrUpdate(r.ctx, r.Client, storageClient, func() error {
if storageClient.Status.ConsumerID == "" {
token, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath, nil)
token, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath, nil, services.ClientRole)
if err != nil {
return fmt.Errorf("unable to generate onboarding token: %v", err)
}
Expand Down
5 changes: 4 additions & 1 deletion controllers/util/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,21 @@ import (
// GenerateOnboardingToken generates a token valid for a duration of "tokenLifetimeInHours".
// The token content is predefined and signed by the private key which'll be read from supplied "privateKeyPath".
// The storageQuotaInGiB is optional, and it is used to limit the storage of PVC in the application cluster.
func GenerateOnboardingToken(tokenLifetimeInHours int, privateKeyPath string, storageQuotaInGiB *uint) (string, error) {
func GenerateOnboardingToken(tokenLifetimeInHours int, privateKeyPath string, storageQuotaInGiB *uint, role services.Role) (string, error) {
tokenExpirationDate := time.Now().
Add(time.Duration(tokenLifetimeInHours) * time.Hour).
Unix()

ticket := services.OnboardingTicket{
ID: uuid.New().String(),
ExpirationDate: tokenExpirationDate,
Role: role,
}

if storageQuotaInGiB != nil {
ticket.StorageQuotaInGiB = *storageQuotaInGiB
}

payload, err := json.Marshal(ticket)
if err != nil {
return "", fmt.Errorf("failed to marshal the payload: %v", err)
Expand Down
9 changes: 9 additions & 0 deletions services/types.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package services

type Role string

const (
ClientRole Role = "client"
MirroringPeerRole Role = "mirroring-peer"
)

type OnboardingTicket struct {
ID string `json:"id"`
ExpirationDate int64 `json:"expirationDate,string"`
StorageQuotaInGiB uint `json:"storageQuotaInGiB,omitempty"`
// Role can be either client or mirroring-peer
Role Role `json:"role,string"`
}
37 changes: 25 additions & 12 deletions services/ux-backend/handlers/onboardingtokens/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import (
"fmt"
"math"
"net/http"
"strings"

"github.com/red-hat-storage/ocs-operator/v4/controllers/util"
"github.com/red-hat-storage/ocs-operator/v4/services"
"github.com/red-hat-storage/ocs-operator/v4/services/ux-backend/handlers"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
Expand All @@ -33,31 +35,42 @@ func HandleMessage(w http.ResponseWriter, r *http.Request, tokenLifetimeInHours

func handlePost(w http.ResponseWriter, r *http.Request, tokenLifetimeInHours int) {
var storageQuotaInGiB *uint
// to ensure backward compatibility, if the body is empty, we assume it to be client
role := services.ClientRole
// When ContentLength is 0 that means request body is empty and
// storage quota is unlimited
var err error
if r.ContentLength != 0 {
var quota = struct {
var body = struct {
Role string `json:"role"`
Value uint `json:"value"`
Unit string `json:"unit"`
}{}
if err = json.NewDecoder(r.Body).Decode(&quota); err != nil {
if err = json.NewDecoder(r.Body).Decode(&body); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

if quota.Value == 0 || quota.Value > math.MaxInt {
http.Error(w, fmt.Sprintf("invalid value sent in request body, value should be greater than 0 and less than %v: %v", math.MaxInt, quota.Value), http.StatusBadRequest)
return
}
unitAsGiB, ok := unitToGib[quota.Unit]
if !ok {
http.Error(w, fmt.Sprintf("invalid Unit type sent in request body, Valid types are [Gi,Ti,Pi]: %v", quota.Unit), http.StatusBadRequest)
if strings.ToLower(body.Role) == string(services.MirroringPeerRole) {
role = services.MirroringPeerRole
} else if strings.ToLower(body.Role) == string(services.ClientRole) || body.Role == "" {
// to ensure backward compatibility, if the role is empty, we assume it to be client
role = services.ClientRole
if body.Value == 0 || body.Value > math.MaxInt {
http.Error(w, fmt.Sprintf("invalid value sent in request body, value should be greater than 0 and less than %v: %v", math.MaxInt, body.Value), http.StatusBadRequest)
return
}
unitAsGiB, ok := unitToGib[body.Unit]
if !ok {
http.Error(w, fmt.Sprintf("invalid Unit type sent in request body, Valid types are [Gi,Ti,Pi]: %v", body.Unit), http.StatusBadRequest)
return
}
storageQuotaInGiB = ptr.To(unitAsGiB * body.Value)
} else {
http.Error(w, fmt.Sprintf("invalid Role sent in request body, Valid roles are [mirroring-peer,client]: %v", body.Role), http.StatusBadRequest)
return
}
storageQuotaInGiB = ptr.To(unitAsGiB * quota.Value)
}
if onboardingToken, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath, storageQuotaInGiB); err != nil {
if onboardingToken, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath, storageQuotaInGiB, role); err != nil {
klog.Errorf("failed to get onboardig token: %v", err)
w.WriteHeader(http.StatusInternalServerError)
w.Header().Set("Content-Type", handlers.ContentTypeTextPlain)
Expand Down

0 comments on commit a3b7ebd

Please sign in to comment.