github.com/vmware/govmomi@v0.51.0/crypto/manager_kmip.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package crypto 6 7 import ( 8 "context" 9 "fmt" 10 11 "github.com/vmware/govmomi/object" 12 "github.com/vmware/govmomi/vim25" 13 "github.com/vmware/govmomi/vim25/methods" 14 "github.com/vmware/govmomi/vim25/types" 15 ) 16 17 const ( 18 CheckKeyAvailable = int32(0x01) 19 CheckKeyUsedByVms = int32(0x02) 20 CheckKeyUsedByHosts = int32(0x04) 21 CheckKeyUsedByOther = int32(0x08) 22 ) 23 24 type ManagerKmip struct { 25 object.Common 26 } 27 28 // GetManagerKmip wraps NewManager, returning ErrNotSupported when the client is 29 // not connected to a vCenter instance. 30 func GetManagerKmip(c *vim25.Client) (*ManagerKmip, error) { 31 if c.ServiceContent.CryptoManager == nil { 32 return nil, object.ErrNotSupported 33 } 34 return NewManagerKmip(c), nil 35 } 36 37 func NewManagerKmip(c *vim25.Client) *ManagerKmip { 38 m := ManagerKmip{ 39 Common: object.NewCommon(c, *c.ServiceContent.CryptoManager), 40 } 41 return &m 42 } 43 44 func (m ManagerKmip) ListKmipServers( 45 ctx context.Context, 46 limit *int32) ([]types.KmipClusterInfo, error) { 47 48 req := types.ListKmipServers{ 49 This: m.Reference(), 50 Limit: limit, 51 } 52 res, err := methods.ListKmipServers(ctx, m.Client(), &req) 53 if err != nil { 54 return nil, err 55 } 56 return res.Returnval, nil 57 } 58 59 func (m ManagerKmip) IsDefaultProviderNative( 60 ctx context.Context, 61 entity *types.ManagedObjectReference, 62 defaultsToParent bool) (bool, error) { 63 64 defaultProviderID, err := m.GetDefaultKmsClusterID( 65 ctx, entity, defaultsToParent) 66 if err != nil { 67 return false, err 68 } 69 if defaultProviderID == "" { 70 return false, nil 71 } 72 return m.IsNativeProvider(ctx, defaultProviderID) 73 } 74 75 func (m ManagerKmip) IsNativeProvider( 76 ctx context.Context, 77 providerID string) (bool, error) { 78 79 info, err := m.GetClusterStatus(ctx, providerID) 80 if err != nil { 81 return false, err 82 } 83 if info == nil { 84 return false, nil 85 } 86 return info.ManagementType == string( 87 types.KmipClusterInfoKmsManagementTypeNativeProvider), nil 88 } 89 90 func (m ManagerKmip) GetDefaultKmsClusterID( 91 ctx context.Context, 92 entity *types.ManagedObjectReference, 93 defaultsToParent bool) (string, error) { 94 95 req := types.GetDefaultKmsCluster{ 96 This: m.Reference(), 97 Entity: entity, 98 DefaultsToParent: &defaultsToParent, 99 } 100 res, err := methods.GetDefaultKmsCluster(ctx, m.Client(), &req) 101 if err != nil { 102 return "", err 103 } 104 if res.Returnval != nil { 105 return res.Returnval.Id, nil 106 } 107 return "", nil 108 } 109 110 func (m ManagerKmip) GetStatus( 111 ctx context.Context, 112 clusters ...types.KmipClusterInfo) ([]types.CryptoManagerKmipClusterStatus, error) { 113 114 req := types.RetrieveKmipServersStatus_Task{ 115 This: m.Reference(), 116 Clusters: clusters, 117 } 118 res, err := methods.RetrieveKmipServersStatus_Task(ctx, m.Client(), &req) 119 if err != nil { 120 return nil, err 121 } 122 123 task := object.NewTask(m.Client(), res.Returnval) 124 taskInfo, err := task.WaitForResult(ctx) 125 if err != nil { 126 return nil, err 127 } 128 129 if taskInfo.Result == nil { 130 return nil, nil 131 } 132 result, ok := taskInfo.Result.(types.ArrayOfCryptoManagerKmipClusterStatus) 133 if !ok { 134 return nil, nil 135 } 136 if len(result.CryptoManagerKmipClusterStatus) == 0 { 137 return nil, nil 138 } 139 140 return result.CryptoManagerKmipClusterStatus, nil 141 } 142 143 func (m ManagerKmip) GetClusterStatus( 144 ctx context.Context, 145 providerID string) (*types.CryptoManagerKmipClusterStatus, error) { 146 147 result, err := m.GetStatus( 148 ctx, 149 types.KmipClusterInfo{ 150 ClusterId: types.KeyProviderId{ 151 Id: providerID, 152 }, 153 }) 154 if err != nil { 155 return nil, err 156 } 157 if len(result) == 0 { 158 return nil, fmt.Errorf("invalid cluster ID") 159 } 160 return &result[0], nil 161 } 162 163 func (m ManagerKmip) GetServerStatus( 164 ctx context.Context, 165 providerID, serverName string) (*types.CryptoManagerKmipServerStatus, error) { 166 167 result, err := m.GetStatus( 168 ctx, 169 types.KmipClusterInfo{ 170 ClusterId: types.KeyProviderId{ 171 Id: providerID, 172 }, 173 Servers: []types.KmipServerInfo{ 174 { 175 Name: serverName, 176 }, 177 }, 178 }) 179 if err != nil { 180 return nil, err 181 } 182 if len(result) == 0 { 183 return nil, fmt.Errorf("invalid cluster ID") 184 } 185 if len(result[0].Servers) == 0 { 186 return nil, fmt.Errorf("invalid server name") 187 } 188 return &result[0].Servers[0], nil 189 } 190 191 func (m ManagerKmip) MarkDefault( 192 ctx context.Context, 193 providerID string) error { 194 195 req := types.MarkDefault{ 196 This: m.Reference(), 197 ClusterId: types.KeyProviderId{Id: providerID}, 198 } 199 _, err := methods.MarkDefault(ctx, m.Client(), &req) 200 if err != nil { 201 return err 202 } 203 return nil 204 } 205 206 func (m ManagerKmip) SetDefaultKmsClusterId( 207 ctx context.Context, 208 providerID string, 209 entity *types.ManagedObjectReference) error { 210 211 req := types.SetDefaultKmsCluster{ 212 This: m.Reference(), 213 Entity: entity, 214 } 215 if providerID != "" { 216 req.ClusterId = &types.KeyProviderId{ 217 Id: providerID, 218 } 219 } 220 _, err := methods.SetDefaultKmsCluster(ctx, m.Client(), &req) 221 if err != nil { 222 return err 223 } 224 return nil 225 } 226 227 func (m ManagerKmip) RegisterKmsCluster( 228 ctx context.Context, 229 providerID string, 230 managementType types.KmipClusterInfoKmsManagementType) error { 231 232 req := types.RegisterKmsCluster{ 233 This: m.Reference(), 234 ClusterId: types.KeyProviderId{ 235 Id: providerID, 236 }, 237 ManagementType: string(managementType), 238 } 239 _, err := methods.RegisterKmsCluster(ctx, m.Client(), &req) 240 if err != nil { 241 return err 242 } 243 return nil 244 } 245 246 func (m ManagerKmip) UnregisterKmsCluster( 247 ctx context.Context, 248 providerID string) error { 249 250 req := types.UnregisterKmsCluster{ 251 This: m.Reference(), 252 ClusterId: types.KeyProviderId{ 253 Id: providerID, 254 }, 255 } 256 _, err := methods.UnregisterKmsCluster(ctx, m.Client(), &req) 257 if err != nil { 258 return err 259 } 260 return nil 261 } 262 263 func (m ManagerKmip) RegisterKmipServer( 264 ctx context.Context, 265 server types.KmipServerSpec) error { 266 267 req := types.RegisterKmipServer{ 268 This: m.Reference(), 269 Server: server, 270 } 271 _, err := methods.RegisterKmipServer(ctx, m.Client(), &req) 272 if err != nil { 273 return err 274 } 275 return nil 276 } 277 278 func (m ManagerKmip) UpdateKmipServer( 279 ctx context.Context, 280 server types.KmipServerSpec) error { 281 282 req := types.UpdateKmipServer{ 283 This: m.Reference(), 284 Server: server, 285 } 286 _, err := methods.UpdateKmipServer(ctx, m.Client(), &req) 287 if err != nil { 288 return err 289 } 290 return nil 291 } 292 293 func (m ManagerKmip) RemoveKmipServer( 294 ctx context.Context, 295 providerID, serverName string) error { 296 297 req := types.RemoveKmipServer{ 298 This: m.Reference(), 299 ClusterId: types.KeyProviderId{ 300 Id: providerID, 301 }, 302 ServerName: serverName, 303 } 304 _, err := methods.RemoveKmipServer(ctx, m.Client(), &req) 305 if err != nil { 306 return err 307 } 308 return nil 309 } 310 311 func (m ManagerKmip) QueryCryptoKeyStatus( 312 ctx context.Context, 313 ids []types.CryptoKeyId, 314 check int32) ([]types.CryptoManagerKmipCryptoKeyStatus, error) { 315 316 req := types.QueryCryptoKeyStatus{ 317 This: m.Reference(), 318 KeyIds: ids, 319 CheckKeyBitMap: check, 320 } 321 322 res, err := methods.QueryCryptoKeyStatus(ctx, m.Client(), &req) 323 if err != nil { 324 return nil, err 325 } 326 return res.Returnval, nil 327 } 328 329 func (m ManagerKmip) ListKeys( 330 ctx context.Context, 331 limit *int32) ([]types.CryptoKeyId, error) { 332 333 req := types.ListKeys{ 334 This: m.Reference(), 335 Limit: limit, 336 } 337 res, err := methods.ListKeys(ctx, m.Client(), &req) 338 if err != nil { 339 return nil, err 340 } 341 return res.Returnval, nil 342 } 343 344 const keyStateNotActiveOrEnabled = string(types.CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateNotActiveOrEnabled) 345 346 // IsValidKey returns true if QueryCryptoKeyStatus results indicate the key is available or unavailable reason is `KeyStateNotActiveOrEnabled`. 347 // This method is only valid for standard providers and will always return false for native providers. 348 func (m ManagerKmip) IsValidKey( 349 ctx context.Context, 350 providerID, 351 keyID string) (bool, error) { 352 353 id := []types.CryptoKeyId{{ 354 KeyId: keyID, 355 ProviderId: &types.KeyProviderId{ 356 Id: providerID, 357 }}, 358 } 359 360 res, err := m.QueryCryptoKeyStatus(ctx, id, CheckKeyAvailable) 361 if err != nil { 362 return false, err 363 } 364 365 for _, status := range res { 366 if status.KeyAvailable != nil && *status.KeyAvailable { 367 return true, nil 368 } 369 370 if status.Reason == keyStateNotActiveOrEnabled { 371 return true, nil 372 } 373 } 374 375 return false, nil 376 } 377 378 func (m ManagerKmip) IsValidProvider( 379 ctx context.Context, 380 providerID string) (bool, error) { 381 382 clusters, err := m.ListKmipServers(ctx, nil) 383 if err != nil { 384 return false, err 385 } 386 387 for i := range clusters { 388 if clusters[i].ClusterId.Id == providerID { 389 return true, nil 390 } 391 } 392 393 return false, nil 394 } 395 396 func (m ManagerKmip) IsValidServer( 397 ctx context.Context, 398 providerID, serverName string) (bool, error) { 399 400 clusters, err := m.ListKmipServers(ctx, nil) 401 if err != nil { 402 return false, err 403 } 404 405 for i := range clusters { 406 if clusters[i].ClusterId.Id == providerID { 407 for j := range clusters[i].Servers { 408 if clusters[i].Servers[j].Name == serverName { 409 return true, nil 410 } 411 } 412 } 413 } 414 415 return false, nil 416 } 417 418 func (m ManagerKmip) GenerateKey( 419 ctx context.Context, 420 providerID string) (string, error) { 421 422 req := types.GenerateKey{ 423 This: m.Reference(), 424 } 425 426 if providerID != "" { 427 req.KeyProvider = &types.KeyProviderId{ 428 Id: providerID, 429 } 430 } 431 res, err := methods.GenerateKey(ctx, m.Client(), &req) 432 if err != nil { 433 return "", err 434 } 435 if !res.Returnval.Success { 436 err := generateKeyError{reason: res.Returnval.Reason} 437 if res.Returnval.Fault != nil { 438 err.LocalizedMethodFault = *res.Returnval.Fault 439 } 440 return "", err 441 } 442 return res.Returnval.KeyId.KeyId, nil 443 } 444 445 func (m ManagerKmip) RemoveKeys( 446 ctx context.Context, 447 ids []types.CryptoKeyId, 448 force bool) error { 449 450 req := types.RemoveKeys{ 451 This: m.Reference(), 452 Keys: ids, 453 Force: force, 454 } 455 456 _, err := methods.RemoveKeys(ctx, m.Client(), &req) 457 return err 458 } 459 460 type generateKeyError struct { 461 types.LocalizedMethodFault 462 reason string 463 } 464 465 func (e generateKeyError) Error() string { 466 467 return e.reason 468 } 469 470 func (e generateKeyError) GetLocalizedMethodFault() *types.LocalizedMethodFault { 471 return &e.LocalizedMethodFault 472 }