github.com/hashicorp/vault/sdk@v0.13.0/logical/logical.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package logical 5 6 import ( 7 "context" 8 9 log "github.com/hashicorp/go-hclog" 10 ) 11 12 // BackendType is the type of backend that is being implemented 13 type BackendType uint32 14 15 // The these are the types of backends that can be derived from 16 // logical.Backend 17 const ( 18 TypeUnknown BackendType = 0 // This is also the zero-value for BackendType 19 TypeLogical BackendType = 1 20 TypeCredential BackendType = 2 21 ) 22 23 // Stringer implementation 24 func (b BackendType) String() string { 25 switch b { 26 case TypeLogical: 27 return "secret" 28 case TypeCredential: 29 return "auth" 30 } 31 32 return "unknown" 33 } 34 35 // Backend interface must be implemented to be "mountable" at 36 // a given path. Requests flow through a router which has various mount 37 // points that flow to a logical backend. The logic of each backend is flexible, 38 // and this is what allows materialized keys to function. There can be specialized 39 // logical backends for various upstreams (Consul, PostgreSQL, MySQL, etc) that can 40 // interact with remote APIs to generate keys dynamically. This interface also 41 // allows for a "procfs" like interaction, as internal state can be exposed by 42 // acting like a logical backend and being mounted. 43 type Backend interface { 44 // Initialize is used to initialize a plugin after it has been mounted. 45 Initialize(context.Context, *InitializationRequest) error 46 47 // HandleRequest is used to handle a request and generate a response. 48 // The backends must check the operation type and handle appropriately. 49 HandleRequest(context.Context, *Request) (*Response, error) 50 51 // SpecialPaths is a list of paths that are special in some way. 52 // See PathType for the types of special paths. The key is the type 53 // of the special path, and the value is a list of paths for this type. 54 // This is not a regular expression but is an exact match. If the path 55 // ends in '*' then it is a prefix-based match. The '*' can only appear 56 // at the end. 57 SpecialPaths() *Paths 58 59 // System provides an interface to access certain system configuration 60 // information, such as globally configured default and max lease TTLs. 61 System() SystemView 62 63 // Logger provides an interface to access the underlying logger. This 64 // is useful when a struct embeds a Backend-implemented struct that 65 // contains a private instance of logger. 66 Logger() log.Logger 67 68 // HandleExistenceCheck is used to handle a request and generate a response 69 // indicating whether the given path exists or not; this is used to 70 // understand whether the request must have a Create or Update capability 71 // ACL applied. The first bool indicates whether an existence check 72 // function was found for the backend; the second indicates whether, if an 73 // existence check function was found, the item exists or not. 74 HandleExistenceCheck(context.Context, *Request) (bool, bool, error) 75 76 // Cleanup is invoked during an unmount of a backend to allow it to 77 // handle any cleanup like connection closing or releasing of file handles. 78 Cleanup(context.Context) 79 80 // InvalidateKey may be invoked when an object is modified that belongs 81 // to the backend. The backend can use this to clear any caches or reset 82 // internal state as needed. 83 InvalidateKey(context.Context, string) 84 85 // Setup is used to set up the backend based on the provided backend 86 // configuration. 87 Setup(context.Context, *BackendConfig) error 88 89 // Type returns the BackendType for the particular backend 90 Type() BackendType 91 } 92 93 // BackendConfig is provided to the factory to initialize the backend 94 type BackendConfig struct { 95 // View should not be stored, and should only be used for initialization 96 StorageView Storage 97 98 // The backend should use this logger. The log should not contain any secrets. 99 Logger log.Logger 100 101 // System provides a view into a subset of safe system information that 102 // is useful for backends, such as the default/max lease TTLs 103 System SystemView 104 105 // BackendUUID is a unique identifier provided to this backend. It's useful 106 // when a backend needs a consistent and unique string without using storage. 107 BackendUUID string 108 109 // Config is the opaque user configuration provided when mounting 110 Config map[string]string 111 112 // EventsSender provides a mechanism to interact with Vault events. 113 EventsSender EventSender 114 } 115 116 // Factory is the factory function to create a logical backend. 117 type Factory func(context.Context, *BackendConfig) (Backend, error) 118 119 // Paths is the structure of special paths that is used for SpecialPaths. 120 type Paths struct { 121 // Root are the API paths that require a root token to access 122 Root []string 123 124 // Unauthenticated are the API paths that can be accessed without any auth. 125 // These can't be regular expressions, it is either exact match, a prefix 126 // match and/or a wildcard match. For prefix match, append '*' as a suffix. 127 // For a wildcard match, use '+' in the segment to match any identifier 128 // (e.g. 'foo/+/bar'). Note that '+' can't be adjacent to a non-slash. 129 Unauthenticated []string 130 131 // LocalStorage are storage paths (prefixes) that are local to this cluster; 132 // this indicates that these paths should not be replicated across performance clusters 133 // (DR replication is unaffected). 134 LocalStorage []string 135 136 // SealWrapStorage are storage paths that, when using a capable seal, 137 // should be seal wrapped with extra encryption. It is exact matching 138 // unless it ends with '/' in which case it will be treated as a prefix. 139 SealWrapStorage []string 140 141 // WriteForwardedStorage are storage paths that, when running on a PR 142 // Secondary cluster, cause a GRPC call up to the PR Primary cluster's 143 // active node to handle storage.Put(...) and storage.Delete(...) events. 144 // These paths MUST include a {{clusterId}} literal, which the write layer 145 // will resolve to this cluster's UUID ("replication set" identifier). 146 // storage.List(...) and storage.Get(...) operations occur from the 147 // locally replicated data set, but can use path template expansion to be 148 // identifier agnostic. 149 // 150 // These paths require careful considerations by developers to use. In 151 // particular, writes on secondary clusters will not appear (when a 152 // corresponding read is issued immediately after a write) until the 153 // replication from primary->secondary has occurred. This replication 154 // triggers an InvalidateKey(...) call on the secondary, which can be 155 // used to detect the write has finished syncing. However, this will 156 // likely occur after the request has finished, so it is important to 157 // not block on this occurring. 158 // 159 // On standby nodes, like all storage write operations, this will trigger 160 // an ErrReadOnly return. 161 WriteForwardedStorage []string 162 163 // Binary paths are those whose request bodies should not be assumed to 164 // be JSON encoded, and for which the backend will decode values for auditing 165 Binary []string 166 167 // Limited paths are storage paths that require special-cased request 168 // limiting. 169 // 170 // This was initially added to separate limiting of "write" requests 171 // (limits.WriteLimiter) from limiting for CPU-bound pki/issue requests 172 // (limits.SpecialPathLimiter). Other plugins might also choose to mark 173 // paths if they don't follow a typical resource usage pattern. 174 // 175 // For more details, consult limits/registry.go. 176 Limited []string 177 } 178 179 type Auditor interface { 180 AuditRequest(ctx context.Context, input *LogInput) error 181 AuditResponse(ctx context.Context, input *LogInput) error 182 } 183 184 type PluginVersion struct { 185 Version string 186 } 187 188 // PluginVersioner is an optional interface to return version info. 189 type PluginVersioner interface { 190 // PluginVersion returns the version for the backend 191 PluginVersion() PluginVersion 192 } 193 194 var EmptyPluginVersion = PluginVersion{""}