Skip to content

Commit

Permalink
changes to onboarding token to include subjectRole in body
Browse files Browse the repository at this point in the history
Signed-off-by: Rewant Soni <[email protected]>
  • Loading branch information
rewantsoni committed Sep 4, 2024
1 parent 6ed794c commit 77748d8
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 17 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
3 changes: 2 additions & 1 deletion controllers/util/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ 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.OnboardingSubjectRole) (string, error) {
tokenExpirationDate := time.Now().
Add(time.Duration(tokenLifetimeInHours) * time.Hour).
Unix()

ticket := services.OnboardingTicket{
ID: uuid.New().String(),
ExpirationDate: tokenExpirationDate,
SubjectRole: role,
}
if storageQuotaInGiB != nil {
ticket.StorageQuotaInGiB = *storageQuotaInGiB
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 OnboardingSubjectRole string

const (
ClientRole OnboardingSubjectRole = "ocs-client"
PeerRole OnboardingSubjectRole = "ocs-peer"
)

type OnboardingTicket struct {
ID string `json:"id"`
ExpirationDate int64 `json:"expirationDate,string"`
StorageQuotaInGiB uint `json:"storageQuotaInGiB,omitempty"`
// OnboardingSubjectRole can be either ocs-client or ocs-peer
SubjectRole OnboardingSubjectRole `json:"subjectRole,string"`
}
45 changes: 30 additions & 15 deletions services/ux-backend/handlers/onboardingtokens/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ 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,32 +36,44 @@ 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 role 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 {
Value uint `json:"value"`
Unit string `json:"unit"`
var body = struct {
SubjectRole string `json:"subjectRole"`
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)
if strings.ToLower(body.SubjectRole) == string(services.PeerRole) {
role = services.PeerRole
} else if strings.ToLower(body.SubjectRole) == string(services.ClientRole) || body.SubjectRole == "" {
// 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 OnboardingSubjectRole sent in request body, Valid roles are [mirroring-peer,client]: %v", body.SubjectRole), 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)
return
}
storageQuotaInGiB = ptr.To(unitAsGiB * quota.Value)
}
if onboardingToken, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath, storageQuotaInGiB); err != nil {
klog.Errorf("failed to get onboardig token: %v", err)

if onboardingToken, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath, storageQuotaInGiB, role); err != nil {
klog.Errorf("failed to get onboarding token: %v", err)
w.WriteHeader(http.StatusInternalServerError)
w.Header().Set("Content-Type", handlers.ContentTypeTextPlain)

Expand Down

0 comments on commit 77748d8

Please sign in to comment.