-
Notifications
You must be signed in to change notification settings - Fork 84
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
Save extracted credentials into a secret #775
Save extracted credentials into a secret #775
Conversation
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.
minor suggestion
creds, err := runtime.Provider.GetExtractedCredential(id, clusterConfig.Namespace) | ||
if err != nil { | ||
switch { | ||
case err == runtime.ErrCredentialsNotFound: |
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.
runtime.ErrCredentialsNotFound
is extracted credentials were not found
clients.ErrCredentialsNotFound
is credentials were not found
apb.ErrExtractedCredentialsNotFound
is credentials not found
Maybe instead of using different vars for a similar message, use one variable at the bottom of the call, clients.ErrCredentialsNotFound
, and bubble that up to the top level and at each instance that sees the error identify where the error was seen.
// /pkg/apb.go
switch {
case err == runtime.ErrCredentialsNotFound:
log.Debugf("APB error: extracted credential secret not found - %v", id)
return nil, ErrExtractedCredentialsNotFound
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.
So here is my thinking on why each package has its own NotFound Error.
I don't want the error to bleed across package boundaries. Right now runtime package is only called by apb. I think we should keep it that way. The same is not currently true of the client, but eventually, we need to encapsulate the client calls in the runtime package.
I think this allows a user who wants to override the runtime package calls for extracted credentials can send back the runtime error and now our APB package can use that. Does that make sense what I was trying to do?
Would love to hear thoughts on this approach.
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 understand your point about which pkg calling another pkg. That part is fine with me. It just seems silly we have three different vars in three different pkgs saying almost exactly the same thing. A follow up to this could be adding an error pkg with all the error constants.
@@ -94,7 +96,14 @@ func NewRuntime() { | |||
panic(err.Error()) | |||
} | |||
|
|||
Provider = &provider{coe: cluster} | |||
var c ExtractedCredential | |||
if extCreds == 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.
Can you explain why we should have this if/else?
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 nil we will use the default extracted credentials. This should be in the godoc for the function and will add now.
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 I understand more what this is now, thanks for the comment.
There's one more thing I want to clear up. How I would create a new ExtractedCredential
object without having some understanding of my runtime from the pkg/app/app.go
pkg?
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 want to clarify my last comment. The runtime interface is structured so that if you call NewRuntime
the Runtime pkg will identify what provider you are using. If we add ExtractedCredential
type to the NewRuntime
call, pkg/app/app.go
needs to know what runtime provider is being used in order to provide a working ExtractedCredential
type. The reason for that is because ExtractedCredential
is stored in a cluster specific resource, a secret. My point is I don't think we want to pass ExtractedCredential
as a param to NewRuntime
, rather we should add it behind the runtime interface it be initialized after the NewRuntime
call.
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.
pkg/app/app.go needs to know what runtime provider is being used in order to provide a working ExtractedCredential type. The reason for that is because ExtractedCredential is stored in a cluster-specific resource, a secret
This would certainly be a problem if we had more then k8s as a provider. Currently, we don't and even the CreateSandbox...
functions relay on core k8s clients and not the provider. I don't think this is a problem currently. We are tracking a better way to override and change the runtime, which I agree we should do. But this needs to be overridable by anyone who is vendoring the project and wants to change this behavior.
Updating this to show what I mean by just using core k8s client is backed into every provider regardless of the cluster specific type.
https://github.com/openshift/ansible-service-broker/blob/master/pkg/runtime/runtime.go#L150
The sandbox will only ever use k8s client, because we only support k8s and openshift. Because of this I think it is currently a valid assumption that anything that can be done with just k8s will be supported in both the clusters that we currently support. The default extracted credentials does that.
Caught up with @shawn-hurley to coordinate this PR and #773 since they're in direct conflict. Plan is to bring in #773 first and then rework this PR on top of it. Coming back to review this afterwards. |
d2ab460
to
3785197
Compare
3785197
to
dd46b5b
Compare
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.
Spoke with Shawn, in order to get the behavior we want here we're going to need to rework the runtime pkg. There's an issue to track this. In the meantime, we'll add a param to NewRuntime
to allow this override.
@@ -20,7 +18,7 @@ metadata: | |||
<labels provided> | |||
``` | |||
|
|||
[Gob encoding](https://godoc.org/encoding/gob) will allow us to save arbitrary data in the secret for a key. The secrets keys will look rational to a user who looks at the created secret. This user would need permissions to see the secret, but if someone is looking at the secret making it obvious what data is in there will be helpful. | |||
To encode the credentials in a generic way, we must marshal a `map[string]interface{}` so that we can retrieve the data. This is not how I wanted the secret to look, but will allow anyone to use the credentials and will allow us to retrieve the credentials without writing our own gob parser. |
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.
+1
@@ -84,6 +84,13 @@ func (e *executor) Bind( | |||
return | |||
} | |||
|
|||
labels := map[string]string{"apbAction": "bind", "apbName": instance.Spec.FQName} | |||
err = runtime.Provider.CreateExtractedCredential(bindingID, clusterConfig.Namespace, creds.Credentials, labels) |
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.
bind.go change looks good.
if err != nil { | ||
log.Errorf("unable to delete the extracted credentials - %v", err) | ||
e.actionFinishedWithError(err) | ||
return |
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.
Wasn't there some issue that @eriknelson was recently looking at about deleting extracted credentials that might not exist? Will this re-introduce that problem?
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.
Yeah it will, think this is where it might make sense for us to have our own error type, and skip the action finished call. Log with INFO level.
Bind(instance *ServiceInstance, parameters *Parameters) <-chan StatusMessage | ||
Unbind(instance *ServiceInstance, parameters *Parameters) <-chan StatusMessage | ||
Bind(instance *ServiceInstance, parameters *Parameters, bindingID string) <-chan StatusMessage | ||
Unbind(instance *ServiceInstance, parameters *Parameters, bindingID string) <-chan StatusMessage |
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.
okay, acceptable to add bindingID
// Please use this method with caution. | ||
func SetExtractedCredentials(id string, creds *ExtractedCredentials) error { | ||
return runtime.Provider.CreateExtractedCredential(id, clusterConfig.Namespace, creds.Credentials, 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.
👍 ext_creds.go looks good.
@@ -257,7 +257,7 @@ func CreateApp() App { | |||
// Intiialize the cluster config. | |||
apb.InitializeClusterConfig(app.config.GetSubConfig("openshift")) | |||
if app.broker, err = broker.NewAnsibleBroker( | |||
app.dao, app.registry, *app.engine, app.config.GetSubConfig("broker"), | |||
app.dao, app.registry, *app.engine, app.config.GetSubConfig("broker"), app.config.GetString("openshift.namespace"), |
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.
👍 app.go
} | ||
|
||
// NewAnsibleBroker - Creates a new ansible broker | ||
func NewAnsibleBroker(dao dao.Dao, | ||
registry []registries.Registry, | ||
engine WorkEngine, | ||
brokerConfig *config.Config) (*AnsibleBroker, error) { | ||
brokerConfig *config.Config, | ||
namespace string) (*AnsibleBroker, 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.
that's very erik of you 😆
bindExtCreds, err := a.dao.GetExtractedCredentials(bindInstance.ID.String()) | ||
if err != nil && !client.IsKeyNotFound(err) { | ||
bindExtCreds, err := apb.GetExtractedCredentials(bindInstance.ID.String()) | ||
if err != nil && err != apb.ErrExtractedCredentialsNotFound { |
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.
👍 broker.go
looks good
return err | ||
} | ||
return 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.
👍 client/kubernetes.go
looks good
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.
Just the item that @jmrodri mentioned in deprovision and unbind. Otherwise, looking good.
@@ -41,6 +42,11 @@ const ( | |||
GatherCredentialsCommand = "broker-bind-creds" | |||
) | |||
|
|||
var ( | |||
// ErrExtractedCredentialsNotFound - Extracted Credentials are not found. | |||
ErrExtractedCredentialsNotFound = fmt.Errorf("credentials not found") |
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.
👍
@@ -70,6 +70,13 @@ func (e *executor) Unbind( | |||
e.actionFinishedWithError(err) | |||
return | |||
} | |||
// Delete the binding extracted credential here. | |||
err = runtime.Provider.DeleteExtractedCredential(bindingID, clusterConfig.Namespace) | |||
if 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 we might want to just log this at an info level if it's a miss error instead of finishing with error here too.
96d4950
to
144133f
Compare
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'm seeing:
[2018-02-27T19:10:33.086Z] [DEBUG] - executor::actionFinishedWithSuccess
[2018-02-27T19:10:33.086Z] [WARNING] - executor::actionFinishedWithSuccess was called, but the statusChan was already closed!
During what should be a failed provision.
Test:
- Create new project and provision mediawiki in that project with admin/admin as the password. This is expected to hard fail because it does not accept the same vals.
We shouldn't be seeing success called in this case.
@eriknelson I have updated and tested based on our quick conversation. |
@shawn-hurley cool, will test again this morning. |
* initial commit * Fixing marshal and unmarshal of data. * fixing binding * adding documentation for creating a new runtime. * fixing provision issue when no extracted credentials occurs. * fix for unbind.go * move action hooks to base methods for provision and update.
Describe what this PR does and why we need it:
This PR will implement #768
Changes proposed in this pull request
Add kubernetes client methods to interact with extracted credentials in the namespace.Add runtime methods for interacting with extracted credentials. These methods should be overridable.Remove all dao implementation and interface methods regarding extracted credentials.Remove all instances of interacting with dao extracted credentials in thebroker
package. Add back call to APB package to get extracted credentials when needed.Add exposed method on APB that will retrieve the extracted credentials.Update APB package to create/save/delete extracted credentials for the correct actions. this should call the correctruntime
package methods.