2026-04-06 15:48:37 +05:30
// Copyright IBM Corp. 2020, 2026
2021-10-14 11:56:08 -04:00
// SPDX-License-Identifier: BUSL-1.1
2023-02-02 17:15:17 -08:00
2020-09-24 03:31:26 -04:00
package base
import (
"context"
"fmt"
2024-02-23 12:19:46 -05:00
"net"
"net/url"
"strconv"
2020-09-24 03:31:26 -04:00
"strings"
2022-10-28 15:52:06 -04:00
"github.com/hashicorp/boundary/globals"
2024-02-23 12:19:46 -05:00
aliastar "github.com/hashicorp/boundary/internal/alias/target"
2020-09-24 03:31:26 -04:00
"github.com/hashicorp/boundary/internal/auth/password"
2024-02-23 12:19:46 -05:00
credstatic "github.com/hashicorp/boundary/internal/credential/static"
credstore "github.com/hashicorp/boundary/internal/credential/static/store"
2020-09-24 03:31:26 -04:00
"github.com/hashicorp/boundary/internal/db"
2023-04-24 19:27:41 -04:00
"github.com/hashicorp/boundary/internal/errors"
2020-09-24 03:31:26 -04:00
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
2023-04-24 19:27:41 -04:00
"github.com/hashicorp/boundary/internal/plugin"
2020-09-24 03:31:26 -04:00
"github.com/hashicorp/boundary/internal/target"
2023-11-02 16:03:47 -04:00
"github.com/hashicorp/boundary/internal/target/tcp"
2020-09-24 03:31:26 -04:00
"github.com/hashicorp/boundary/internal/types/scope"
2023-04-24 19:27:41 -04:00
"github.com/hashicorp/boundary/internal/util"
2021-09-28 09:40:12 -04:00
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
2021-07-14 17:31:58 -07:00
"github.com/hashicorp/go-secure-stdlib/base62"
2020-09-24 03:31:26 -04:00
)
2020-10-01 10:51:54 -04:00
func ( b * Server ) CreateInitialLoginRole ( ctx context . Context ) ( * iam . Role , error ) {
rw := db . New ( b . Database )
2022-05-13 13:53:22 -04:00
kmsCache , err := kms . New ( ctx , rw , rw )
2020-10-01 10:51:54 -04:00
if err != nil {
return nil , fmt . Errorf ( "error creating kms cache: %w" , err )
}
if err := kmsCache . AddExternalWrappers (
2022-03-16 17:04:07 -04:00
b . Context ,
2020-10-01 10:51:54 -04:00
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
return nil , fmt . Errorf ( "error adding config keys to kms: %w" , err )
}
2023-06-06 17:09:08 -04:00
iamRepo , err := iam . NewRepository ( ctx , rw , rw , kmsCache , iam . WithRandomReader ( b . SecureRandomReader ))
2020-10-01 10:51:54 -04:00
if err != nil {
return nil , fmt . Errorf ( "unable to create repo for initial login role: %w" , err )
}
2023-06-06 17:09:08 -04:00
pr , err := iam . NewRole ( ctx ,
scope . Global . String (),
2024-01-23 14:33:09 -05:00
iam . WithName ( "Login Grants" ),
iam . WithDescription ( `Role created for login capability for unauthenticated users` ),
2020-10-01 10:51:54 -04:00
)
if err != nil {
return nil , fmt . Errorf ( "error creating in memory role for generated grants: %w" , err )
}
2024-01-23 14:33:09 -05:00
role , _ , _ , _ , err := iamRepo . CreateRole ( ctx , pr )
2020-10-01 10:51:54 -04:00
if err != nil {
return nil , fmt . Errorf ( "error creating role for default generated grants: %w" , err )
}
2022-09-19 09:59:18 -04:00
if _ , err := iamRepo . AddRoleGrants ( ctx , role . PublicId , role . Version , [] string {
2024-01-17 23:54:49 -08:00
"ids=*;type=scope;actions=list,no-op" ,
2024-01-23 14:33:09 -05:00
"ids=*;type=auth-method;actions=list,authenticate" ,
"ids=*;type=auth-token;actions=read:self,delete:self" ,
2020-10-01 10:51:54 -04:00
}); err != nil {
2024-01-23 14:33:09 -05:00
return nil , fmt . Errorf ( "error creating grant for initial login grants: %w" , err )
}
if _ , err := iamRepo . AddPrincipalRoles ( ctx , role . PublicId , role . Version + 1 , [] string { globals . AnonymousUserId }); err != nil {
return nil , fmt . Errorf ( "error adding principal to role for initial login grants: %w" , err )
2020-10-01 10:51:54 -04:00
}
2024-01-23 14:33:09 -05:00
if _ , _ , err := iamRepo . SetRoleGrantScopes ( ctx , role . PublicId , role . Version + 2 , [] string { "this" , "descendants" }); err != nil {
return nil , fmt . Errorf ( "error adding scope grants to role for initial login grants: %w" , err )
}
return role , nil
}
func ( b * Server ) CreateInitialAuthenticatedUserRole ( ctx context . Context , opt ... Option ) ( * iam . Role , error ) {
rw := db . New ( b . Database )
kmsCache , err := kms . New ( ctx , rw , rw )
if err != nil {
return nil , fmt . Errorf ( "error creating kms cache: %w" , err )
}
if err := kmsCache . AddExternalWrappers (
b . Context ,
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
return nil , fmt . Errorf ( "error adding config keys to kms: %w" , err )
}
iamRepo , err := iam . NewRepository ( ctx , rw , rw , kmsCache , iam . WithRandomReader ( b . SecureRandomReader ))
if err != nil {
return nil , fmt . Errorf ( "unable to create repo for initial login role: %w" , err )
}
pr , err := iam . NewRole ( ctx ,
scope . Global . String (),
iam . WithName ( "Authenticated User Grants" ),
iam . WithDescription ( `Role created for account self-management, and other initial authenticated user grants` ),
)
if err != nil {
return nil , fmt . Errorf ( "error creating in memory role for generated grants: %w" , err )
}
role , _ , _ , _ , err := iamRepo . CreateRole ( ctx , pr )
if err != nil {
return nil , fmt . Errorf ( "error creating role for default generated grants: %w" , err )
}
grants := [] string {
"ids=*;type=scope;actions=read" ,
"ids=*;type=auth-token;actions=list" ,
"ids={{.Account.Id}};actions=read,change-password" ,
"ids=*;type=session;actions=list,read:self,cancel:self" ,
2024-04-17 08:26:46 -07:00
"ids={{.User.Id}};type=user;actions=list-resolvable-aliases" ,
2024-01-23 14:33:09 -05:00
}
opts := GetOpts ( opt ... )
if opts . withAuthUserTargetAuthorizeSessionGrant {
grants = append ( grants , "ids=*;type=target;actions=list,read,authorize-session" )
} else {
grants = append ( grants , "ids=*;type=target;actions=list,read" )
}
if _ , err := iamRepo . AddRoleGrants ( ctx , role . PublicId , role . Version , grants ); err != nil {
return nil , fmt . Errorf ( "error creating grant for initial authenticated user grants: %w" , err )
}
if _ , err := iamRepo . AddPrincipalRoles ( ctx , role . PublicId , role . Version + 1 , [] string { globals . AnyAuthenticatedUserId }); err != nil {
return nil , fmt . Errorf ( "error adding principal to role for initial authenticated user grants: %w" , err )
}
if _ , _ , err := iamRepo . SetRoleGrantScopes ( ctx , role . PublicId , role . Version + 2 , [] string { "this" , "descendants" }); err != nil {
return nil , fmt . Errorf ( "error adding scope grants to role for initial authenticated user grants: %w" , err )
2020-10-01 10:51:54 -04:00
}
return role , nil
}
2021-04-08 20:54:32 -04:00
func ( b * Server ) CreateInitialPasswordAuthMethod ( ctx context . Context ) ( * password . AuthMethod , * iam . User , error ) {
2020-09-24 03:31:26 -04:00
rw := db . New ( b . Database )
2022-05-13 13:53:22 -04:00
kmsCache , err := kms . New ( ctx , rw , rw )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error creating kms cache: %w" , err )
2020-09-24 03:31:26 -04:00
}
if err := kmsCache . AddExternalWrappers (
2022-03-16 17:04:07 -04:00
b . Context ,
2020-09-24 03:31:26 -04:00
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error adding config keys to kms: %w" , err )
2020-09-24 03:31:26 -04:00
}
// Create the dev auth method
2025-12-09 09:50:36 +05:30
pwRepo , err := password . NewRepository ( ctx , rw , rw , kmsCache , password . WithRandomReader ( b . SecureRandomReader ))
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error creating password repo: %w" , err )
2020-09-24 03:31:26 -04:00
}
2023-06-06 17:09:08 -04:00
authMethod , err := password . NewAuthMethod ( ctx , scope . Global . String (),
2021-04-08 20:54:32 -04:00
password . WithName ( "Generated global scope initial password auth method" ),
2026-10-12 10:20:06 -07:00
password . WithDescription ( "Provides initial administrative and unprivileged authentication into Threshold" ),
2020-09-24 12:54:40 -04:00
)
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error creating new in memory auth method: %w" , err )
2020-09-24 03:31:26 -04:00
}
2021-04-08 20:54:32 -04:00
if b . DevPasswordAuthMethodId == "" {
2023-06-06 17:09:08 -04:00
b . DevPasswordAuthMethodId , err = db . NewPublicId ( ctx , globals . PasswordAuthMethodPrefix )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error generating initial auth method id: %w" , err )
2020-09-24 03:31:26 -04:00
}
}
2022-09-19 09:59:18 -04:00
am , err := pwRepo . CreateAuthMethod ( ctx , authMethod ,
2021-04-08 20:54:32 -04:00
password . WithPublicId ( b . DevPasswordAuthMethodId ))
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error saving auth method to the db: %w" , err )
2020-09-24 03:31:26 -04:00
}
2021-04-08 20:54:32 -04:00
b . InfoKeys = append ( b . InfoKeys , "generated password auth method id" )
b . Info [ "generated password auth method id" ] = b . DevPasswordAuthMethodId
// we'll designate the initial password auth method as the primary auth
// method id for the global scope, which means the auth method will create
// users on first login. Otherwise, the operator would have to create both
// a password account and a user associated with the new account, before
// users could successfully login.
2023-06-06 17:09:08 -04:00
iamRepo , err := iam . NewRepository ( ctx , rw , rw , kmsCache )
2021-04-08 20:54:32 -04:00
if err != nil {
return nil , nil , fmt . Errorf ( "unable to create iam repo: %w" , err )
}
globalScope , err := iamRepo . LookupScope ( ctx , scope . Global . String ())
if err != nil {
return nil , nil , fmt . Errorf ( "unable to lookup global scope: %w" , err )
}
globalScope . PrimaryAuthMethodId = am . PublicId
if _ , _ , err := iamRepo . UpdateScope ( ctx , globalScope , globalScope . Version , [] string { "PrimaryAuthMethodId" }); err != nil {
return nil , nil , fmt . Errorf ( "unable to set primary auth method for global scope: %w" , err )
}
2020-09-24 03:31:26 -04:00
2021-06-04 09:35:51 -05:00
createUser := func ( loginName , loginPassword , userId , accountId string , admin bool ) ( * iam . User , error ) {
2021-02-11 13:14:18 -05:00
// Create the dev admin user
if loginName == "" {
2021-04-08 20:54:32 -04:00
return nil , fmt . Errorf ( "empty login name" )
2021-02-11 13:14:18 -05:00
}
2021-03-16 08:42:08 -07:00
if loginPassword == "" {
2021-04-08 20:54:32 -04:00
return nil , fmt . Errorf ( "empty login name" )
}
if userId == "" {
return nil , fmt . Errorf ( "empty user id" )
2021-02-11 13:14:18 -05:00
}
typeStr := "admin"
if ! admin {
typeStr = "unprivileged"
}
b . InfoKeys = append ( b . InfoKeys , fmt . Sprintf ( "generated %s password" , typeStr ))
b . Info [ fmt . Sprintf ( "generated %s password" , typeStr )] = loginPassword
2023-06-06 17:09:08 -04:00
acct , err := password . NewAccount ( ctx , am . PublicId , password . WithLoginName ( loginName ))
2020-09-24 03:31:26 -04:00
if err != nil {
2021-04-08 20:54:32 -04:00
return nil , fmt . Errorf ( "error creating new in memory password auth account: %w" , err )
2020-09-24 03:31:26 -04:00
}
2021-06-04 09:35:51 -05:00
acct , err = pwRepo . CreateAccount (
2022-09-19 09:59:18 -04:00
ctx ,
2021-06-04 09:35:51 -05:00
scope . Global . String (),
acct ,
password . WithPassword ( loginPassword ),
password . WithPublicId ( accountId ),
2025-12-09 09:50:36 +05:30
password . WithRandomReader ( b . SecureRandomReader ),
2021-06-04 09:35:51 -05:00
)
2020-09-24 03:31:26 -04:00
if err != nil {
2021-02-11 13:14:18 -05:00
return nil , fmt . Errorf ( "error saving auth account to the db: %w" , err )
2020-09-24 03:31:26 -04:00
}
2021-02-11 13:14:18 -05:00
b . InfoKeys = append ( b . InfoKeys , fmt . Sprintf ( "generated %s login name" , typeStr ))
b . Info [ fmt . Sprintf ( "generated %s login name" , typeStr )] = acct . GetLoginName ()
2020-09-24 03:31:26 -04:00
2023-06-06 17:09:08 -04:00
iamRepo , err := iam . NewRepository ( ctx , rw , rw , kmsCache , iam . WithRandomReader ( b . SecureRandomReader ))
2021-02-11 13:14:18 -05:00
if err != nil {
2021-04-08 20:54:32 -04:00
return nil , fmt . Errorf ( "unable to create iam repo: %w" , err )
2021-02-11 13:14:18 -05:00
}
2020-09-24 03:31:26 -04:00
2021-02-11 13:14:18 -05:00
// Create a new user and associate it with the account
opts := [] iam . Option {
iam . WithPublicId ( userId ),
}
if admin {
opts = append ( opts ,
iam . WithName ( "admin" ),
2021-11-04 09:34:01 -04:00
iam . WithDescription ( fmt . Sprintf ( `Initial admin user within the "%s" scope` , scope . Global . String ())),
2021-02-11 13:14:18 -05:00
)
} else {
opts = append ( opts ,
iam . WithName ( "user" ),
iam . WithDescription ( "Initial unprivileged user" ),
)
}
2023-06-06 17:09:08 -04:00
u , err := iam . NewUser ( ctx , scope . Global . String (), opts ... )
2021-02-11 13:14:18 -05:00
if err != nil {
return nil , fmt . Errorf ( "error creating in memory user: %w" , err )
}
2022-09-19 09:59:18 -04:00
if u , err = iamRepo . CreateUser ( ctx , u , opts ... ); err != nil {
2021-02-11 13:14:18 -05:00
return nil , fmt . Errorf ( "error creating initial %s user: %w" , typeStr , err )
}
2022-09-19 09:59:18 -04:00
if _ , err = iamRepo . AddUserAccounts ( ctx , u . GetPublicId (), u . GetVersion (), [] string { acct . GetPublicId ()}); err != nil {
2021-02-11 13:14:18 -05:00
return nil , fmt . Errorf ( "error associating initial %s user with account: %w" , typeStr , err )
}
if ! admin {
return u , nil
}
// Create a role tying them together
2023-06-06 17:09:08 -04:00
pr , err := iam . NewRole ( ctx ,
scope . Global . String (),
2021-02-11 13:14:18 -05:00
iam . WithName ( "Administration" ),
2024-01-23 14:33:09 -05:00
iam . WithDescription ( "Provides admin grants within all scopes to the initial admin user" ),
2021-02-11 13:14:18 -05:00
)
if err != nil {
return nil , fmt . Errorf ( "error creating in memory role for generated grants: %w" , err )
}
2024-01-23 14:33:09 -05:00
adminRole , _ , _ , _ , err := iamRepo . CreateRole ( ctx , pr )
2021-02-11 13:14:18 -05:00
if err != nil {
return nil , fmt . Errorf ( "error creating role for default generated grants: %w" , err )
}
2024-01-23 14:33:09 -05:00
if _ , err := iamRepo . AddRoleGrants ( ctx , adminRole . PublicId , adminRole . Version , [] string { "ids=*;type=*;actions=*" }); err != nil {
2021-02-11 13:14:18 -05:00
return nil , fmt . Errorf ( "error creating grant for default generated grants: %w" , err )
}
2024-01-23 14:33:09 -05:00
if _ , err := iamRepo . AddPrincipalRoles ( ctx , adminRole . PublicId , adminRole . Version + 1 , [] string { u . GetPublicId ()}, nil ); err != nil {
2021-02-11 13:14:18 -05:00
return nil , fmt . Errorf ( "error adding principal to role for default generated grants: %w" , err )
}
2024-01-23 14:33:09 -05:00
if _ , _ , err := iamRepo . SetRoleGrantScopes ( ctx , adminRole . PublicId , adminRole . Version + 2 , [] string { "this" , "descendants" }); err != nil {
return nil , fmt . Errorf ( "error adding scope grants to role for default generated grants: %w" , err )
}
2021-02-11 13:14:18 -05:00
return u , nil
2020-09-24 03:31:26 -04:00
}
2021-04-08 20:54:32 -04:00
switch {
case b . DevUnprivilegedLoginName == "" ,
b . DevUnprivilegedPassword == "" ,
b . DevUnprivilegedUserId == "" :
default :
2021-06-04 09:35:51 -05:00
_ , err := createUser ( b . DevUnprivilegedLoginName , b . DevUnprivilegedPassword , b . DevUnprivilegedUserId , b . DevUnprivilegedPasswordAccountId , false )
2020-09-24 03:31:26 -04:00
if err != nil {
2021-02-11 13:14:18 -05:00
return nil , nil , err
2020-09-24 03:31:26 -04:00
}
2021-04-08 20:54:32 -04:00
}
if b . DevLoginName == "" {
b . DevLoginName , err = base62 . Random ( 10 )
if err != nil {
return nil , nil , fmt . Errorf ( "unable to generate login name: %w" , err )
}
b . DevLoginName = strings . ToLower ( b . DevLoginName )
}
if b . DevPassword == "" {
b . DevPassword , err = base62 . Random ( 20 )
if err != nil {
return nil , nil , fmt . Errorf ( "unable to generate password: %w" , err )
}
}
if b . DevUserId == "" {
2023-06-06 17:09:08 -04:00
b . DevUserId , err = db . NewPublicId ( ctx , globals . UserPrefix )
2021-04-08 20:54:32 -04:00
if err != nil {
return nil , nil , fmt . Errorf ( "error generating initial user id: %w" , err )
}
2020-09-24 03:31:26 -04:00
}
2021-06-04 09:35:51 -05:00
u , err := createUser ( b . DevLoginName , b . DevPassword , b . DevUserId , b . DevPasswordAccountId , true )
2020-09-24 03:31:26 -04:00
if err != nil {
2021-02-11 13:14:18 -05:00
return nil , nil , err
2020-09-24 03:31:26 -04:00
}
2020-09-24 12:54:40 -04:00
return am , u , nil
2020-09-24 03:31:26 -04:00
}
2024-01-23 14:33:09 -05:00
func ( b * Server ) CreateInitialScopes ( ctx context . Context , opt ... Option ) ( * iam . Scope , * iam . Scope , error ) {
2020-09-24 03:31:26 -04:00
rw := db . New ( b . Database )
2022-05-13 13:53:22 -04:00
kmsCache , err := kms . New ( ctx , rw , rw )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error creating kms cache: %w" , err )
2020-09-24 03:31:26 -04:00
}
2022-03-16 17:04:07 -04:00
if err := kmsCache . AddExternalWrappers (
b . Context ,
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error adding config keys to kms: %w" , err )
2020-09-24 03:31:26 -04:00
}
2024-01-23 14:33:09 -05:00
opts := GetOpts ( opt ... )
2023-06-06 17:09:08 -04:00
iamRepo , err := iam . NewRepository ( ctx , rw , rw , kmsCache )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error creating scopes repository: %w" , err )
2020-09-24 03:31:26 -04:00
}
// Create the scopes
if b . DevOrgId == "" {
2023-06-06 17:09:08 -04:00
b . DevOrgId , err = db . NewPublicId ( ctx , scope . Org . Prefix ())
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error generating initial org id: %w" , err )
2020-09-24 03:31:26 -04:00
}
}
2024-01-23 14:33:09 -05:00
iamOpts := [] iam . Option {
2020-09-24 03:31:26 -04:00
iam . WithName ( "Generated org scope" ),
2026-10-12 10:20:06 -07:00
iam . WithDescription ( "Provides an initial org scope in Threshold" ),
2020-09-24 03:31:26 -04:00
iam . WithRandomReader ( b . SecureRandomReader ),
iam . WithPublicId ( b . DevOrgId ),
}
2024-01-23 14:33:09 -05:00
if len ( opts . withIamOptions ) > 0 {
iamOpts = append ( iamOpts , opts . withIamOptions ... )
}
orgScope , err := iam . NewOrg ( ctx , iamOpts ... )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error creating new in memory org scope: %w" , err )
2020-09-24 03:31:26 -04:00
}
2024-01-23 14:33:09 -05:00
orgScope , err = iamRepo . CreateScope ( ctx , orgScope , b . DevUserId , iamOpts ... )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error saving org scope to the db: %w" , err )
2020-09-24 03:31:26 -04:00
}
b . InfoKeys = append ( b . InfoKeys , "generated org scope id" )
b . Info [ "generated org scope id" ] = b . DevOrgId
if b . DevProjectId == "" {
2023-06-06 17:09:08 -04:00
b . DevProjectId , err = db . NewPublicId ( ctx , scope . Project . Prefix ())
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error generating initial project id: %w" , err )
2020-09-24 03:31:26 -04:00
}
}
2024-01-23 14:33:09 -05:00
iamOpts = [] iam . Option {
2020-09-24 03:31:26 -04:00
iam . WithName ( "Generated project scope" ),
2026-10-12 10:20:06 -07:00
iam . WithDescription ( "Provides an initial project scope in Threshold" ),
2020-09-24 03:31:26 -04:00
iam . WithRandomReader ( b . SecureRandomReader ),
iam . WithPublicId ( b . DevProjectId ),
}
2024-01-23 14:33:09 -05:00
if len ( opts . withIamOptions ) > 0 {
iamOpts = append ( iamOpts , opts . withIamOptions ... )
}
projScope , err := iam . NewProject ( ctx , b . DevOrgId , iamOpts ... )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error creating new in memory project scope: %w" , err )
2020-09-24 03:31:26 -04:00
}
2024-01-23 14:33:09 -05:00
projScope , err = iamRepo . CreateScope ( ctx , projScope , b . DevUserId , iamOpts ... )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error saving project scope to the db: %w" , err )
2020-09-24 03:31:26 -04:00
}
b . InfoKeys = append ( b . InfoKeys , "generated project scope id" )
b . Info [ "generated project scope id" ] = b . DevProjectId
2020-09-24 12:54:40 -04:00
return orgScope , projScope , nil
2020-09-24 03:31:26 -04:00
}
2020-09-24 12:54:40 -04:00
func ( b * Server ) CreateInitialHostResources ( ctx context . Context ) ( * static . HostCatalog , * static . HostSet , * static . Host , error ) {
2020-09-24 03:31:26 -04:00
rw := db . New ( b . Database )
2022-05-13 13:53:22 -04:00
kmsCache , err := kms . New ( ctx , rw , rw )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error creating kms cache: %w" , err )
2020-09-24 03:31:26 -04:00
}
if err := kmsCache . AddExternalWrappers (
2022-03-16 17:04:07 -04:00
b . Context ,
2020-09-24 03:31:26 -04:00
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error adding config keys to kms: %w" , err )
2020-09-24 03:31:26 -04:00
}
2023-06-06 17:09:08 -04:00
staticRepo , err := static . NewRepository ( ctx , rw , rw , kmsCache )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error creating static repository: %w" , err )
2020-09-24 03:31:26 -04:00
}
// Host Catalog
if b . DevHostCatalogId == "" {
2023-06-06 17:09:08 -04:00
b . DevHostCatalogId , err = db . NewPublicId ( ctx , globals . StaticHostCatalogPrefix )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error generating initial host catalog id: %w" , err )
2020-09-24 03:31:26 -04:00
}
}
opts := [] static . Option {
static . WithName ( "Generated host catalog" ),
2026-10-12 10:20:06 -07:00
static . WithDescription ( "Provides an initial host catalog in Threshold" ),
2020-09-24 03:31:26 -04:00
static . WithPublicId ( b . DevHostCatalogId ),
}
2023-06-06 17:09:08 -04:00
hc , err := static . NewHostCatalog ( ctx , b . DevProjectId , opts ... )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error creating in memory host catalog: %w" , err )
2020-09-24 03:31:26 -04:00
}
2022-09-19 09:59:18 -04:00
if hc , err = staticRepo . CreateCatalog ( ctx , hc , opts ... ); err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error saving host catalog to the db: %w" , err )
2020-09-24 03:31:26 -04:00
}
b . InfoKeys = append ( b . InfoKeys , "generated host catalog id" )
b . Info [ "generated host catalog id" ] = b . DevHostCatalogId
// Host
if b . DevHostId == "" {
2023-06-06 17:09:08 -04:00
b . DevHostId , err = db . NewPublicId ( ctx , globals . StaticHostPrefix )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error generating initial host id: %w" , err )
2020-09-24 03:31:26 -04:00
}
}
if b . DevHostAddress == "" {
b . DevHostAddress = "localhost"
}
opts = [] static . Option {
static . WithName ( "Generated host" ),
2026-10-12 10:20:06 -07:00
static . WithDescription ( "Provides an initial host in Threshold" ),
2020-09-24 03:31:26 -04:00
static . WithAddress ( b . DevHostAddress ),
static . WithPublicId ( b . DevHostId ),
}
2023-06-06 17:09:08 -04:00
h , err := static . NewHost ( ctx , hc . PublicId , opts ... )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error creating in memory host: %w" , err )
2020-09-24 03:31:26 -04:00
}
2022-09-19 09:59:18 -04:00
if h , err = staticRepo . CreateHost ( ctx , b . DevProjectId , h , opts ... ); err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error saving host to the db: %w" , err )
2020-09-24 03:31:26 -04:00
}
b . InfoKeys = append ( b . InfoKeys , "generated host id" )
b . Info [ "generated host id" ] = b . DevHostId
// Host Set
if b . DevHostSetId == "" {
2023-06-06 17:09:08 -04:00
b . DevHostSetId , err = db . NewPublicId ( ctx , globals . StaticHostSetPrefix )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error generating initial host set id: %w" , err )
2020-09-24 03:31:26 -04:00
}
}
opts = [] static . Option {
static . WithName ( "Generated host set" ),
2026-10-12 10:20:06 -07:00
static . WithDescription ( "Provides an initial host set in Threshold" ),
2020-09-24 03:31:26 -04:00
static . WithPublicId ( b . DevHostSetId ),
}
2023-06-06 17:09:08 -04:00
hs , err := static . NewHostSet ( ctx , hc . PublicId , opts ... )
2020-09-24 03:31:26 -04:00
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error creating in memory host set: %w" , err )
2020-09-24 03:31:26 -04:00
}
2022-09-19 09:59:18 -04:00
if hs , err = staticRepo . CreateSet ( ctx , b . DevProjectId , hs , opts ... ); err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error saving host set to the db: %w" , err )
2020-09-24 03:31:26 -04:00
}
b . InfoKeys = append ( b . InfoKeys , "generated host set id" )
b . Info [ "generated host set id" ] = b . DevHostSetId
// Associate members
2022-09-19 09:59:18 -04:00
if _ , err := staticRepo . AddSetMembers ( ctx , b . DevProjectId , b . DevHostSetId , hs . GetVersion (), [] string { h . GetPublicId ()}); err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error associating host set to host in the db: %w" , err )
2020-09-24 03:31:26 -04:00
}
2020-09-24 12:54:40 -04:00
return hc , hs , h , nil
2020-09-24 03:31:26 -04:00
}
2022-12-20 20:51:56 +00:00
func ( b * Server ) CreateInitialTargetWithAddress ( ctx context . Context ) ( target . Target , error ) {
2020-09-24 03:31:26 -04:00
rw := db . New ( b . Database )
2022-05-13 13:53:22 -04:00
kmsCache , err := kms . New ( ctx , rw , rw )
2020-09-24 03:31:26 -04:00
if err != nil {
2022-12-20 20:51:56 +00:00
return nil , fmt . Errorf ( "failed to create kms cache: %w" , err )
}
if err := kmsCache . AddExternalWrappers ( ctx , kms . WithRootWrapper ( b . RootKms )); err != nil {
return nil , fmt . Errorf ( "failed to add config keys to kms: %w" , err )
}
2025-12-22 11:30:10 +05:30
targetRepo , err := target . NewRepository ( ctx , rw , rw , kmsCache , target . WithRandomReader ( b . SecureRandomReader ))
2022-12-20 20:51:56 +00:00
if err != nil {
return nil , fmt . Errorf ( "failed to create target repository: %w" , err )
}
2026-10-12 10:20:06 -07:00
// When this function is not called as part of threshold dev (eg: as part of
// threshold database init or tests), generate random target ids.
2022-12-20 20:51:56 +00:00
if len ( b . DevTargetId ) == 0 {
2023-06-06 17:09:08 -04:00
b . DevTargetId , err = db . NewPublicId ( ctx , globals . TcpTargetPrefix )
2022-12-20 20:51:56 +00:00
if err != nil {
return nil , fmt . Errorf ( "failed to generate initial target id: %w" , err )
}
}
if b . DevTargetDefaultPort == 0 {
b . DevTargetDefaultPort = 22
}
if len ( b . DevTargetAddress ) == 0 {
b . DevTargetAddress = "127.0.0.1"
}
opts := [] target . Option {
target . WithName ( "Generated target with a direct address" ),
2026-10-12 10:20:06 -07:00
target . WithDescription ( "Provides an initial target using an address in Threshold" ),
2022-12-20 20:51:56 +00:00
target . WithDefaultPort ( uint32 ( b . DevTargetDefaultPort )),
target . WithSessionMaxSeconds ( uint32 ( b . DevTargetSessionMaxSeconds )),
target . WithSessionConnectionLimit ( int32 ( b . DevTargetSessionConnectionLimit )),
target . WithPublicId ( b . DevTargetId ),
target . WithAddress ( b . DevTargetAddress ),
}
2024-02-23 12:19:46 -05:00
tt , err := b . createTarget ( ctx , targetRepo , opts ... )
if err != nil {
return nil , err
}
b . InfoKeys = append ( b . InfoKeys , "generated target with address id" )
b . Info [ "generated target with address id" ] = b . DevTargetId
return tt , nil
}
func ( b * Server ) createTarget ( ctx context . Context , targetRepo * target . Repository , opts ... target . Option ) ( target . Target , error ) {
2023-11-02 16:03:47 -04:00
t , err := target . New ( ctx , tcp . Subtype , b . DevProjectId , opts ... )
2022-12-20 20:51:56 +00:00
if err != nil {
return nil , fmt . Errorf ( "failed to create target object: %w" , err )
}
2023-03-30 15:19:30 -04:00
tt , err := targetRepo . CreateTarget ( ctx , t , opts ... )
2022-12-20 20:51:56 +00:00
if err != nil {
return nil , fmt . Errorf ( "failed to save target to the db: %w" , err )
}
return tt , nil
}
func ( b * Server ) CreateInitialTargetWithHostSources ( ctx context . Context ) ( target . Target , error ) {
rw := db . New ( b . Database )
kmsCache , err := kms . New ( ctx , rw , rw )
if err != nil {
return nil , fmt . Errorf ( "failed to create kms cache: %w" , err )
2020-09-24 03:31:26 -04:00
}
if err := kmsCache . AddExternalWrappers (
2022-03-16 17:04:07 -04:00
b . Context ,
2020-09-24 03:31:26 -04:00
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
2022-12-20 20:51:56 +00:00
return nil , fmt . Errorf ( "failed to add config keys to kms: %w" , err )
2020-09-24 03:31:26 -04:00
}
2022-08-23 18:44:10 +01:00
targetRepo , err := target . NewRepository ( ctx , rw , rw , kmsCache )
2020-09-24 03:31:26 -04:00
if err != nil {
2022-12-20 20:51:56 +00:00
return nil , fmt . Errorf ( "failed to create target repository: %w" , err )
2020-09-24 03:31:26 -04:00
}
2026-10-12 10:20:06 -07:00
// When this function is not called as part of threshold dev (eg: as part of
// threshold database init or tests), generate random target ids.
2022-12-20 20:51:56 +00:00
if len ( b . DevSecondaryTargetId ) == 0 {
2023-06-06 17:09:08 -04:00
b . DevSecondaryTargetId , err = db . NewPublicId ( ctx , globals . TcpTargetPrefix )
2020-09-24 03:31:26 -04:00
if err != nil {
2022-12-20 20:51:56 +00:00
return nil , fmt . Errorf ( "failed to generate initial secondary target id: %w" , err )
2020-09-24 03:31:26 -04:00
}
}
if b . DevTargetDefaultPort == 0 {
b . DevTargetDefaultPort = 22
}
2022-12-20 20:51:56 +00:00
2020-09-24 03:31:26 -04:00
opts := [] target . Option {
2022-12-20 20:51:56 +00:00
target . WithName ( "Generated target using host sources" ),
2026-10-12 10:20:06 -07:00
target . WithDescription ( "Provides a target using host sources in Threshold" ),
2020-09-24 03:31:26 -04:00
target . WithDefaultPort ( uint32 ( b . DevTargetDefaultPort )),
2020-09-24 17:29:12 -04:00
target . WithSessionMaxSeconds ( uint32 ( b . DevTargetSessionMaxSeconds )),
target . WithSessionConnectionLimit ( int32 ( b . DevTargetSessionConnectionLimit )),
2022-12-20 20:51:56 +00:00
target . WithPublicId ( b . DevSecondaryTargetId ),
2020-09-24 03:31:26 -04:00
}
2024-02-23 12:19:46 -05:00
tt , err := b . createTarget ( ctx , targetRepo , opts ... )
2020-09-24 03:31:26 -04:00
if err != nil {
2024-02-23 12:19:46 -05:00
return nil , err
2020-09-24 03:31:26 -04:00
}
2023-03-30 15:19:30 -04:00
tt , err = targetRepo . AddTargetHostSources ( ctx , tt . GetPublicId (), tt . GetVersion (), [] string { b . DevHostSetId })
2021-10-22 08:51:46 -04:00
if err != nil {
2022-12-20 20:51:56 +00:00
return nil , fmt . Errorf ( "failed to add host source %q to target: %w" , b . DevHostSetId , err )
2021-10-22 08:51:46 -04:00
}
2022-12-20 20:51:56 +00:00
b . InfoKeys = append ( b . InfoKeys , "generated target with host source id" )
b . Info [ "generated target with host source id" ] = b . DevSecondaryTargetId
2020-09-24 03:31:26 -04:00
return tt , nil
}
2021-09-28 09:40:12 -04:00
2024-02-23 12:19:46 -05:00
// Create targets that can be connected to using an alias. The three targets created are:
2026-10-12 10:20:06 -07:00
// - "postgres.boundary.dev": the Threshold dev postgres instance. Uses brokered credentials
2024-02-23 12:19:46 -05:00
// - "www.hashicorp.com": a web target
2024-03-05 17:49:27 -05:00
// - "ssh.boundary.dev": A localhost ssh target
2024-02-23 12:19:46 -05:00
func ( b * Server ) CreateInitialTargetsWithAlias ( ctx context . Context ) error {
rw := db . New ( b . Database )
kmsCache , err := kms . New ( ctx , rw , rw )
if err != nil {
return fmt . Errorf ( "failed to create kms cache: %w" , err )
}
if err := kmsCache . AddExternalWrappers (
b . Context ,
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
return fmt . Errorf ( "failed to add config keys to kms: %w" , err )
}
targetRepo , err := target . NewRepository ( ctx , rw , rw , kmsCache )
if err != nil {
return fmt . Errorf ( "failed to create target repository: %w" , err )
}
credsRepo , err := credstatic . NewRepository ( ctx , rw , rw , kmsCache )
if err != nil {
return fmt . Errorf ( "failed to create creds repository: %w" , err )
}
aliasRepo , err := aliastar . NewRepository ( ctx , rw , rw , kmsCache )
if err != nil {
return fmt . Errorf ( "failed to create alias repository: %w" , err )
}
err = b . createPostgresAliasTarget ( ctx , targetRepo , aliasRepo , credsRepo )
if err != nil {
return fmt . Errorf ( "failed to create postgres alias target: %w" , err )
}
err = b . createWebTarget ( ctx , targetRepo , aliasRepo )
if err != nil {
return fmt . Errorf ( "failed to create web target: %w" , err )
}
err = b . createSshAliasTarget ( ctx , targetRepo , aliasRepo )
if err != nil {
return fmt . Errorf ( "failed to create ssh target: %w" , err )
}
return nil
}
func ( b * Server ) createSshAliasTarget ( ctx context . Context , targetRepo * target . Repository , aliasRepo * aliastar . Repository ) error {
opts := [] target . Option {
target . WithName ( "Generated localhost ssh target with an alias" ),
2026-10-12 10:20:06 -07:00
target . WithDescription ( "Provides an initial localhost target to SSH to using an alias in Threshold" ),
2024-02-23 12:19:46 -05:00
target . WithDefaultPort ( 22 ),
target . WithSessionMaxSeconds ( uint32 ( b . DevTargetSessionMaxSeconds )),
target . WithSessionConnectionLimit ( int32 ( b . DevTargetSessionConnectionLimit )),
target . WithAddress ( "127.0.0.1" ),
}
t , err := b . createTarget ( ctx , targetRepo , opts ... )
if err != nil {
return err
}
sshAlias := "ssh.boundary.dev"
a , err := aliastar . NewAlias ( ctx , "global" , sshAlias , aliastar . WithDestinationId ( t . GetPublicId ()))
if err != nil {
return fmt . Errorf ( "failed to create alias object %w" , err )
}
_ , err = aliasRepo . CreateAlias ( ctx , a )
if err != nil {
return fmt . Errorf ( "failed to save alias to the db %w" , err )
}
b . InfoKeys = append ( b . InfoKeys , "generated ssh target with alias" )
b . Info [ "generated ssh target with alias" ] = sshAlias
return nil
}
func ( b * Server ) createPostgresAliasTarget ( ctx context . Context ,
targetRepo * target . Repository ,
aliasRepo * aliastar . Repository ,
credsRepo * credstatic . Repository ,
) error {
u , err := url . Parse ( b . DatabaseUrl )
if err != nil {
return fmt . Errorf ( "failed to parse DB url: %w" , err )
}
host , portStr , err := net . SplitHostPort ( u . Host )
if err != nil {
return fmt . Errorf ( "failed to split host port from DB url: %w" , err )
}
port , err := strconv . ParseUint ( portStr , 10 , 32 )
if err != nil {
return fmt . Errorf ( "failed to parse postgres port from DB url: %w" , err )
}
dbname := strings . Trim ( u . Path , "/" )
opts := [] target . Option {
target . WithName ( "Generated local postgres target with alias" ),
2026-10-12 10:20:06 -07:00
target . WithDescription ( fmt . Sprintf ( "Provides a local postgres target using aliasing in Threshold. Connect using the flag `-dbname %s`" , dbname )),
2024-02-23 12:19:46 -05:00
target . WithDefaultPort ( uint32 ( port )),
target . WithAddress ( host ),
target . WithSessionMaxSeconds ( uint32 ( b . DevTargetSessionMaxSeconds )),
target . WithSessionConnectionLimit ( int32 ( b . DevTargetSessionConnectionLimit )),
}
t , err := b . createTarget ( ctx , targetRepo , opts ... )
if err != nil {
return err
}
cs , err := credsRepo . CreateCredentialStore ( ctx ,
& credstatic . CredentialStore {
CredentialStore : & credstore . CredentialStore {
ProjectId : b . DevProjectId ,
},
},
)
if err != nil {
return fmt . Errorf ( "failed to create cred store: %w" , err )
}
cred , err := credstatic . NewUsernamePasswordCredential ( cs . PublicId , "postgres" , "password" )
if err != nil {
return fmt . Errorf ( "failed to create cred: %w" , err )
}
upCred , err := credsRepo . CreateUsernamePasswordCredential ( ctx , b . DevProjectId , cred )
if err != nil {
return fmt . Errorf ( "failed to store cred: %w" , err )
}
_ , err = targetRepo . AddTargetCredentialSources (
ctx ,
t . GetPublicId (),
t . GetVersion (),
target . CredentialSources {
BrokeredCredentialIds : [] string { upCred . PublicId },
},
)
if err != nil {
return fmt . Errorf ( "failed to associate cred to target: %w" , err )
}
postgresAlias := "postgres.boundary.dev"
a , err := aliastar . NewAlias ( ctx , "global" , postgresAlias , aliastar . WithDestinationId ( t . GetPublicId ()))
if err != nil {
return fmt . Errorf ( "failed to create alias object %w" , err )
}
_ , err = aliasRepo . CreateAlias ( ctx , a )
if err != nil {
return fmt . Errorf ( "failed to save alias to the db %w" , err )
}
b . InfoKeys = append ( b . InfoKeys , "generated postgres target with alias" )
b . Info [ "generated postgres target with alias" ] = postgresAlias
return nil
}
func ( b * Server ) createWebTarget ( ctx context . Context ,
targetRepo * target . Repository ,
aliasRepo * aliastar . Repository ,
) error {
opts := [] target . Option {
target . WithName ( "www.hashicorp.com" ),
2026-10-12 10:20:06 -07:00
target . WithDescription ( "Provides an initial web target using an address in Threshold. Note: Only HTTPS is supported, as this target uses port 443. Alias names for web targets should match the URL for the target." ),
2024-02-23 12:19:46 -05:00
target . WithDefaultPort ( 443 ),
target . WithSessionMaxSeconds ( 5 ),
target . WithSessionConnectionLimit ( int32 ( b . DevTargetSessionConnectionLimit )),
target . WithAddress ( "www.hashicorp.com" ),
}
t , err := b . createTarget ( ctx , targetRepo , opts ... )
if err != nil {
return err
}
2024-02-27 07:35:55 -05:00
webAlias := "www.hashicorp.com"
2024-02-23 12:19:46 -05:00
a , err := aliastar . NewAlias ( ctx , "global" , webAlias , aliastar . WithDestinationId ( t . GetPublicId ()))
if err != nil {
return fmt . Errorf ( "failed to create alias object %w" , err )
}
_ , err = aliasRepo . CreateAlias ( ctx , a )
if err != nil {
return fmt . Errorf ( "failed to save alias to the db %w" , err )
}
b . InfoKeys = append ( b . InfoKeys , "generated web target with alias" )
b . Info [ "generated web target with alias" ] = webAlias
return nil
}
2023-04-24 19:27:41 -04:00
// RegisterPlugin creates a plugin in the database if not present, and flags
// the plugin type based on the flags parameter. If the PluginTypeHost flag is
// set, it also registers the plugin in the shared map of running plugins.
// Since all boundary provided plugins must have a name, a name is required
// when calling RegisterPlugin and will be used even if WithName is provided.
// hostClient must not be nil when host flag is included.
func ( b * Server ) RegisterPlugin ( ctx context . Context , name string , hostClient plgpb . HostPluginServiceClient , flags [] plugin . PluginType , opt ... plugin . Option ) ( * plugin . Plugin , error ) {
const op = "base.(Server).RegisterPlugin"
switch {
case len ( flags ) == 0 :
return nil , errors . New ( ctx , errors . InvalidParameter , op , "plugins must be initialized with at least one plugin type" )
case name == "" :
return nil , errors . New ( ctx , errors . InvalidParameter , op , "no name provided when creating plugin" )
2021-09-29 15:46:42 -07:00
}
2023-04-24 19:27:41 -04:00
2021-09-28 09:40:12 -04:00
rw := db . New ( b . Database )
2023-04-24 19:27:41 -04:00
if b . Kms == nil {
var err error
if b . Kms , err = kms . New ( ctx , rw , rw ); err != nil {
return nil , fmt . Errorf ( "error creating kms cache: %w" , err )
}
2021-09-28 09:40:12 -04:00
}
2023-04-24 19:27:41 -04:00
if err := b . Kms . AddExternalWrappers (
2022-03-16 17:04:07 -04:00
ctx ,
2021-09-28 09:40:12 -04:00
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
return nil , fmt . Errorf ( "error adding config keys to kms: %w" , err )
}
2023-04-24 19:27:41 -04:00
hpRepo , err := plugin . NewRepository ( ctx , rw , rw , b . Kms )
2021-09-28 09:40:12 -04:00
if err != nil {
2023-04-24 19:27:41 -04:00
return nil , fmt . Errorf ( "error creating plugin repository: %w" , err )
2021-09-28 09:40:12 -04:00
}
2023-04-24 19:27:41 -04:00
plg , err := hpRepo . LookupPluginByName ( ctx , name )
2021-09-28 09:40:12 -04:00
if err != nil {
2023-04-24 19:27:41 -04:00
return nil , fmt . Errorf ( "error looking up plugin by name: %w" , err )
2021-09-29 15:46:42 -07:00
}
2023-04-24 19:27:41 -04:00
if plg == nil {
opt = append ( opt , plugin . WithName ( name ))
plg = plugin . NewPlugin ( opt ... )
plg , err = hpRepo . CreatePlugin ( ctx , plg , opt ... )
2021-09-29 15:46:42 -07:00
if err != nil {
2023-04-24 19:27:41 -04:00
return nil , fmt . Errorf ( "error creating plugin: %w" , err )
2021-09-29 15:46:42 -07:00
}
2021-09-28 09:40:12 -04:00
}
2023-04-24 19:27:41 -04:00
// TODO: support flags should be moved to the create/update repo calls before plugins are exposed to users
for _ , flag := range flags {
switch flag {
case plugin . PluginTypeHost :
if util . IsNil ( hostClient ) {
return nil , errors . New ( ctx , errors . InvalidParameter , op , "no host client provided when initializing host plugin" )
}
if err := hpRepo . AddSupportFlag ( ctx , plg , plugin . PluginTypeHost ); err != nil {
return nil , err
}
if b . HostPlugins == nil {
b . HostPlugins = make ( map [ string ] plgpb . HostPluginServiceClient )
}
b . HostPlugins [ plg . GetPublicId ()] = hostClient
case plugin . PluginTypeStorage :
if err := hpRepo . AddSupportFlag ( ctx , plg , plugin . PluginTypeStorage ); err != nil {
return nil , err
}
}
2021-09-28 09:40:12 -04:00
}
2023-04-24 19:27:41 -04:00
return plg , nil
2021-09-28 09:40:12 -04:00
}