-
Notifications
You must be signed in to change notification settings - Fork 184
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
Read secrets for onboarding-token validation #2715
Conversation
Skipping CI for Draft Pull Request. |
controllers/util/provider.go
Outdated
privateSecret := &corev1.Secret{} | ||
privateSecret.Name = onboardingValidationPrivateKeySecretName | ||
privateSecret.Namespace = operatorNamespace | ||
err = cl.Get(ctx, types.NamespacedName{Name: storageClusterName, Namespace: operatorNamespace}, privateSecret) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need to get the storageClusterName
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
storageClusterName is removed
controllers/util/provider.go
Outdated
|
||
pubKeyBytes := privateSecret.Data["key"] | ||
|
||
Block, _ := pem.Decode(pubKeyBytes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pem.Decode(privateSecret.Data["key"])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved
controllers/util/provider.go
Outdated
func newClient() (client.Client, error) { | ||
klog.Info("Setting up k8s client") | ||
scheme := runtime.NewScheme() | ||
if err := v1.AddToScheme(scheme); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think clientgoscheme already registers Kube native APIs. Let's try without the scheme.
Do you think it would be a good idea to remove the mounted secret from the ocs-operator? The mounted secret is used to create the default client. @leelavg |
|
60022a5
to
a98859f
Compare
/retest |
/test go test |
@rchikatw: The specified target(s) for
Use In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
/test all |
controllers/util/provider.go
Outdated
cl, err := newClient() | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read private key: %v", err) | ||
klog.Exitf("failed to create client: %v", err) | ||
} | ||
ctx := context.Background() | ||
operatorNamespace, err := GetOperatorNamespace() | ||
if err != nil { | ||
klog.Exitf("unable to get operator namespace: %v", err) | ||
} | ||
|
||
Block, _ := pem.Decode(pemString) | ||
privateSecret := &corev1.Secret{} | ||
privateSecret.Name = onboardingValidationPrivateKeySecretName | ||
privateSecret.Namespace = operatorNamespace | ||
err1 := cl.Get(ctx, types.NamespacedName{Name: onboardingValidationPrivateKeySecretName, Namespace: operatorNamespace}, privateSecret) | ||
if err1 != nil { | ||
return nil, fmt.Errorf("failed to get private secret: %v", err1) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- There should be no need to create a new client. In most cases this code is being used there is already a client that is used on the call sire of
GenerateOnboardingToken
. It is important to use that client instead of the new client for many reasons, some of which are:
- The client is a cached client and the object is already loaded
- The client is a mock/testing client used for testing and does not execute to a valid k8s API server
- I am not sure you are taking the right approach by trying to load the secret here. This code path was and should be a compute-only code path, this means it will benefit us to not introduce any k8s-specific concerns into it. My approach will be to load the secret outside of the
GenerateOnboardingToken
util and provide the private key payload an argument
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Used existing client on the call site on GenerateOnboardingToken,
-
The secrets are loaded in a separate function and the private key is decoded and passed to the GenerateOnboardingToken
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: Mrudraia The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
52d15b8
to
c72f700
Compare
i see the rebase is not done properly. Can you rebase correctly? Basically, I see 2 commits and one of the commits is unrelated to your changes. |
@@ -36,6 +33,8 @@ func handlePost(w http.ResponseWriter, r *http.Request, tokenLifetimeInHours int | |||
// When ContentLength is 0 that means request body is empty and | |||
// storage quota is unlimited | |||
var err error | |||
var cl client.Client |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where is the kubeclient initialized?
"sigs.k8s.io/controller-runtime/pkg/reconcile" | ||
"sigs.k8s.io/yaml" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this pkg being removed and different pkg added?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is not mine, It accured due to improper rebasing
controllers/util/provider.go
Outdated
// 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pls change or remove irrelevant parts of the comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed the irrelevant comments
controllers/util/provider.go
Outdated
@@ -64,16 +74,28 @@ func GenerateOnboardingToken(tokenLifetimeInHours int, privateKeyPath string, st | |||
return fmt.Sprintf("%s.%s", encodedPayload, encodedSignature), nil | |||
} | |||
|
|||
func readAndDecodePrivateKey(privateKeyPath string) (*rsa.PrivateKey, error) { | |||
pemString, err := os.ReadFile(privateKeyPath) | |||
func DecodePemKey(cl client.Client) (*rsa.PrivateKey, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this func needs to be exported?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function not to be exported, changed the function
e84e5e2
to
e9c31d4
Compare
client, err := newClient() | ||
if err != nil { | ||
klog.Errorf("failed to create new client. %v", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you shouldn't be creating kubeclient for every request, create it in main and use that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Mrudraia I believe main already creates a client and some other endpoints accept that client. Can you please follow that pattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Acknowledge
controllers/util/provider.go
Outdated
privateSecret.Name = onboardingValidationPrivateKeySecretName | ||
privateSecret.Namespace = operatorNamespace | ||
|
||
err = cl.Get(ctx, types.NamespacedName{Name: onboardingValidationPrivateKeySecretName, Namespace: operatorNamespace}, privateSecret) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you have already set ObjectMeta on privateSecret and could do
err = cl.Get(ctx, types.NamespacedName{Name: onboardingValidationPrivateKeySecretName, Namespace: operatorNamespace}, privateSecret) | |
err = cl.Get(ctx, client.ObjectKeyFromObject(privateSecret), privateSecret) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack
controllers/util/provider.go
Outdated
pemString, err := os.ReadFile(privateKeyPath) | ||
func decodePemKey(cl client.Client) (*rsa.PrivateKey, error) { | ||
klog.Info("Decoding the Pem key") | ||
ctx := context.Background() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better to get the context from caller rather than creating one here everytime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@@ -86,3 +90,19 @@ func handleUnsupportedMethod(w http.ResponseWriter, r *http.Request) { | |||
klog.Errorf("failed write data to response writer: %v", err) | |||
} | |||
} | |||
|
|||
func newClient() (client.Client, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a handler and possibly creation of client shouldn't be here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack, removed the code in handler.go and as suggested called from the main.
controllers/util/provider.go
Outdated
privateSecret := &corev1.Secret{} | ||
privateSecret.Name = onboardingValidationPrivateKeySecretName | ||
privateSecret.Namespace = operatorNamespace | ||
|
||
err = cl.Get(ctx, types.NamespacedName{Name: onboardingValidationPrivateKeySecretName, Namespace: operatorNamespace}, privateSecret) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I stated in my previous review, getting the secret content should be done outside of the flow for GenerateOnboardingToken
. The GenerateOnboardingToken
(and all sub-calls under it) should not concern themselves with k8s. This means you need to get the private key string outside this flow and pass it instead of passing in a client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the GenerateOnboardingToken method, privateKey is passed to the function, no k8s query is done inside GenerateOnboardingToken.
fdf2e37
to
859cfef
Compare
services/ux-backend/main.go
Outdated
return k8sClient, nil | ||
} | ||
|
||
func readPrivateKey(cl client.Client) (*rsa.PrivateKey, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not read the private key in the main.go file as it is only called once at the start. It will be a problem if the storage admin rotates the key and the private key changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the reading of private key from main.go, and moved to utils.
d16fedf
to
36a17e7
Compare
/retest |
|
||
privateKey, err := util.ReadPrivateKey(cl) | ||
if err != nil { | ||
fmt.Println("Failed to get private key", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should be of type http.Error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack
@@ -5,6 +5,8 @@ import ( | |||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | |||
) | |||
|
|||
const onboardingValidationPrivateKeySecretName = "onboarding-private-key" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its also defined in storageclient.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed unused code
"time" | ||
|
||
"github.com/google/uuid" | ||
"github.com/red-hat-storage/ocs-operator/v4/services" | ||
) | ||
|
||
// 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". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are updating the parameter type so I would suggest this comment should be update accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack
@@ -225,7 +225,7 @@ func (r *StorageClusterReconciler) SetupWithManager(mgr ctrl.Manager) error { | |||
Owns(&appsv1.Deployment{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). | |||
Owns(&corev1.Service{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). | |||
Owns(&corev1.ConfigMap{}, builder.MatchEveryOwner, builder.WithPredicates(predicate.GenerationChangedPredicate{})). | |||
Owns(&corev1.Secret{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). | |||
Owns(&corev1.Secret{}, builder.MatchEveryOwner, builder.WithPredicates(predicate.GenerationChangedPredicate{})). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this change is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will trigger reconcilation to all owners whenever their is change in secrets.
Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]> Signed-off-by: mrudraia <[email protected]>
r.Log.Info("Unable to get privatekey:") | ||
return reconcile.Result{}, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is an err while reading the private key we should return the err
PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
Close this as a copy is raised already. |
Opened a new PR #2827 |
This PR reads the secrets instead of reading the secrets from the volume mounts.
whenever the new onboarding secrets are created, it takes more time to read the secrets from the volume mounts,
The user clicks the rotate onboarding keys, the kubernetes still uses the old public, private keys , the new keys are mounted later, So this PR will read the secrets directly from the kubernetes secrets.