github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/agent/credentialvalidator/backend.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package credentialvalidator 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/juju/names.v2" 9 10 jujucloud "github.com/juju/juju/cloud" 11 "github.com/juju/juju/state" 12 ) 13 14 // Backend defines behavior that credential validator needs. 15 type Backend interface { 16 // ModelUsesCredential determines if the model uses given cloud credential. 17 ModelUsesCredential(tag names.CloudCredentialTag) (bool, error) 18 19 // ModelCredential retrieves the cloud credential that a model uses. 20 ModelCredential() (*ModelCredential, error) 21 22 // WatchCredential returns a watcher that is keeping an eye on all changes to 23 // a given cloud credential. 24 WatchCredential(names.CloudCredentialTag) state.NotifyWatcher 25 26 // InvalidateModelCredential marks the cloud credential that a current model 27 // uses as invalid. 28 InvalidateModelCredential(reason string) error 29 30 // WatchModelCredential returns a watcher that is keeping an eye on what cloud credential a model uses. 31 WatchModelCredential() (state.NotifyWatcher, error) 32 } 33 34 func NewBackend(st StateAccessor) Backend { 35 return &backend{st} 36 } 37 38 type backend struct { 39 StateAccessor 40 } 41 42 // ModelUsesCredential implements Backend.ModelUsesCredential. 43 func (b *backend) ModelUsesCredential(tag names.CloudCredentialTag) (bool, error) { 44 m, err := b.Model() 45 if err != nil { 46 return false, errors.Trace(err) 47 } 48 modelCredentialTag, exists := m.CloudCredential() 49 return exists && tag == modelCredentialTag, nil 50 } 51 52 // ModelCredential implements Backend.ModelCredential. 53 func (b *backend) ModelCredential() (*ModelCredential, error) { 54 m, err := b.Model() 55 if err != nil { 56 return nil, errors.Trace(err) 57 } 58 59 modelCredentialTag, exists := m.CloudCredential() 60 result := &ModelCredential{Model: m.ModelTag(), Exists: exists} 61 if !exists { 62 // A model credential is not set, we must check if the model 63 // is on the cloud that requires a credential. 64 supportsEmptyAuth, err := b.cloudSupportsNoAuth(m.Cloud()) 65 if err != nil { 66 return nil, errors.Trace(err) 67 } 68 result.Valid = supportsEmptyAuth 69 if !supportsEmptyAuth { 70 // TODO (anastasiamac 2018-11-12) Figure out how to notify the users here - maybe set a model status?... 71 logger.Warningf("model credential is not set for the model but the cloud requires it") 72 } 73 return result, nil 74 } 75 76 result.Credential = modelCredentialTag 77 credential, err := b.CloudCredential(modelCredentialTag) 78 if err != nil { 79 if !errors.IsNotFound(err) { 80 return nil, errors.Trace(err) 81 } 82 // In this situation, a model refers to a credential that does not exist in credentials collection. 83 // TODO (anastasiamac 2018-11-12) Figure out how to notify the users here - maybe set a model status?... 84 logger.Warningf("cloud credential reference is set for the model but the credential content is no longer on the controller") 85 result.Valid = false 86 return result, nil 87 } 88 result.Valid = credential.IsValid() 89 return result, nil 90 } 91 92 // WatchModelCredential implements Backend.WatchModelCredential. 93 func (b *backend) WatchModelCredential() (state.NotifyWatcher, error) { 94 m, err := b.Model() 95 if err != nil { 96 return nil, errors.Trace(err) 97 } 98 return m.WatchModelCredential(), nil 99 } 100 101 func (b *backend) cloudSupportsNoAuth(cloudName string) (bool, error) { 102 cloud, err := b.Cloud(cloudName) 103 if err != nil { 104 return false, errors.Trace(err) 105 } 106 for _, authType := range cloud.AuthTypes { 107 if authType == jujucloud.EmptyAuthType { 108 return true, nil 109 } 110 } 111 return false, nil 112 } 113 114 // ModelCredential stores model's cloud credential information. 115 type ModelCredential struct { 116 // Model is a model tag. 117 Model names.ModelTag 118 119 // Exists indicates whether the model has a cloud credential. 120 // On some clouds, that only require "empty" auth, cloud credential 121 // is not needed for the models to function properly. 122 Exists bool 123 124 // Credential is a cloud credential tag. 125 Credential names.CloudCredentialTag 126 127 // Valid indicates that this model's cloud authentication is valid. 128 // 129 // If this model has a cloud credential setup, 130 // then this property indicates that this credential itself is valid. 131 // 132 // If this model has no cloud credential, then this property indicates 133 // whether or not it is valid for this model to have no credential. 134 // There are some clouds that do not require auth and, hence, 135 // models on these clouds do not require credentials. 136 // 137 // If a model is on the cloud that does require credential and 138 // the model's credential is not set, this property will be set to 'false'. 139 Valid bool 140 }