2020-09-24 03:31:26 -04:00
package base
import (
"context"
"fmt"
"strings"
2021-04-13 16:42:25 -07:00
"github.com/hashicorp/boundary/internal/auth"
2020-09-24 03:31:26 -04:00
"github.com/hashicorp/boundary/internal/auth/password"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/types/scope"
2021-07-12 21:06:22 -04:00
"github.com/hashicorp/shared-secure-libs/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 )
kmsRepo , err := kms . NewRepository ( rw , rw )
if err != nil {
return nil , fmt . Errorf ( "error creating kms repository: %w" , err )
}
kmsCache , err := kms . NewKms ( kmsRepo , kms . WithLogger ( b . Logger . Named ( "kms" )))
if err != nil {
return nil , fmt . Errorf ( "error creating kms cache: %w" , err )
}
if err := kmsCache . AddExternalWrappers (
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
return nil , fmt . Errorf ( "error adding config keys to kms: %w" , err )
}
cancelCtx , cancel := context . WithCancel ( ctx )
2021-02-05 12:58:54 -07:00
defer cancel ()
2020-10-01 10:51:54 -04:00
go func () {
2021-02-05 12:58:54 -07:00
select {
case <- b . ShutdownCh :
cancel ()
case <- cancelCtx . Done ():
}
2020-10-01 10:51:54 -04:00
}()
iamRepo , err := iam . NewRepository ( 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 ( scope . Global . String (),
iam . WithName ( "Login and Default Grants" ),
2021-02-11 13:14:18 -05:00
iam . WithDescription ( `Role created for login capability, account self-management, and other default grants for users of the global scope at its creation time` ),
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 )
}
role , err := iamRepo . CreateRole ( cancelCtx , pr )
if err != nil {
return nil , fmt . Errorf ( "error creating role for default generated grants: %w" , err )
}
if _ , err := iamRepo . AddRoleGrants ( cancelCtx , role . PublicId , role . Version , [] string {
2021-04-23 09:13:37 -05:00
"id=*;type=scope;actions=list,no-op" ,
2020-10-01 10:51:54 -04:00
"id=*;type=auth-method;actions=authenticate,list" ,
"id={{account.id}};actions=read,change-password" ,
2021-04-23 12:45:08 -05:00
"id=*;type=auth-token;actions=list,read:self,delete:self" ,
2020-10-01 10:51:54 -04:00
}); err != nil {
return nil , fmt . Errorf ( "error creating grant for default generated grants: %w" , err )
}
2021-04-13 16:42:25 -07:00
if _ , err := iamRepo . AddPrincipalRoles ( cancelCtx , role . PublicId , role . Version + 1 , [] string { auth . AnonymousUserId }, nil ); err != nil {
2020-10-01 10:51:54 -04:00
return nil , fmt . Errorf ( "error adding principal to role for default generated grants: %w" , err )
}
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 )
kmsRepo , err := kms . NewRepository ( rw , rw )
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error creating kms repository: %w" , err )
2020-09-24 03:31:26 -04:00
}
kmsCache , err := kms . NewKms ( kmsRepo , kms . WithLogger ( b . Logger . Named ( "kms" )))
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 (
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
pwRepo , err := password . NewRepository ( rw , rw , kmsCache )
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
}
2020-09-24 12:54:40 -04:00
authMethod , err := password . NewAuthMethod ( scope . Global . String (),
2021-04-08 20:54:32 -04:00
password . WithName ( "Generated global scope initial password auth method" ),
password . WithDescription ( "Provides initial administrative and unprivileged authentication into Boundary" ),
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 == "" {
b . DevPasswordAuthMethodId , err = db . NewPublicId ( password . AuthMethodPrefix )
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
}
}
cancelCtx , cancel := context . WithCancel ( ctx )
2021-02-05 12:58:54 -07:00
defer cancel ()
2020-09-24 03:31:26 -04:00
go func () {
2021-02-05 12:58:54 -07:00
select {
case <- b . ShutdownCh :
cancel ()
case <- cancelCtx . Done ():
}
2020-09-24 03:31:26 -04:00
}()
2020-09-24 12:54:40 -04:00
am , err := pwRepo . CreateAuthMethod ( cancelCtx , 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.
iamRepo , err := iam . NewRepository ( rw , rw , kmsCache )
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
acct , err := password . NewAccount ( 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 (
cancelCtx ,
scope . Global . String (),
acct ,
password . WithPassword ( loginPassword ),
password . WithPublicId ( accountId ),
)
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
2021-02-11 13:14:18 -05:00
iamRepo , err := iam . NewRepository ( rw , rw , kmsCache , iam . WithRandomReader ( b . SecureRandomReader ))
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" ),
iam . WithDescription ( `Initial admin user within the "global" scope` ),
)
} else {
opts = append ( opts ,
iam . WithName ( "user" ),
iam . WithDescription ( "Initial unprivileged user" ),
)
}
u , err := iam . NewUser ( scope . Global . String (), opts ... )
if err != nil {
return nil , fmt . Errorf ( "error creating in memory user: %w" , err )
}
if u , err = iamRepo . CreateUser ( cancelCtx , u , opts ... ); err != nil {
return nil , fmt . Errorf ( "error creating initial %s user: %w" , typeStr , err )
}
if _ , err = iamRepo . AddUserAccounts ( cancelCtx , u . GetPublicId (), u . GetVersion (), [] string { acct . GetPublicId ()}); err != nil {
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
pr , err := iam . NewRole ( scope . Global . String (),
iam . WithName ( "Administration" ),
iam . WithDescription ( `Provides admin grants within the "global" scope to the initial user` ),
)
if err != nil {
return nil , fmt . Errorf ( "error creating in memory role for generated grants: %w" , err )
}
defPermsRole , err := iamRepo . CreateRole ( cancelCtx , pr )
if err != nil {
return nil , fmt . Errorf ( "error creating role for default generated grants: %w" , err )
}
if _ , err := iamRepo . AddRoleGrants ( cancelCtx , defPermsRole . PublicId , defPermsRole . Version , [] string { "id=*;type=*;actions=*" }); err != nil {
return nil , fmt . Errorf ( "error creating grant for default generated grants: %w" , err )
}
if _ , err := iamRepo . AddPrincipalRoles ( cancelCtx , defPermsRole . PublicId , defPermsRole . Version + 1 , [] string { u . GetPublicId ()}, nil ); err != nil {
return nil , fmt . Errorf ( "error adding principal to role for default generated grants: %w" , err )
}
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 == "" {
b . DevUserId , err = db . NewPublicId ( iam . UserPrefix )
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
}
2020-09-24 12:54:40 -04:00
func ( b * Server ) CreateInitialScopes ( ctx context . Context ) ( * iam . Scope , * iam . Scope , error ) {
2020-09-24 03:31:26 -04:00
rw := db . New ( b . Database )
kmsRepo , err := kms . NewRepository ( rw , rw )
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , fmt . Errorf ( "error creating kms repository: %w" , err )
2020-09-24 03:31:26 -04:00
}
kmsCache , err := kms . NewKms ( kmsRepo , kms . WithLogger ( b . Logger . Named ( "kms" )))
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
}
2021-03-16 08:42:08 -07:00
if err := kmsCache . AddExternalWrappers ( 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
}
cancelCtx , cancel := context . WithCancel ( ctx )
2021-02-05 12:58:54 -07:00
defer cancel ()
2020-09-24 03:31:26 -04:00
go func () {
2021-02-05 12:58:54 -07:00
select {
case <- b . ShutdownCh :
cancel ()
case <- cancelCtx . Done ():
}
2020-09-24 03:31:26 -04:00
}()
iamRepo , err := iam . NewRepository ( rw , rw , kmsCache )
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 == "" {
b . DevOrgId , err = db . NewPublicId ( scope . Org . Prefix ())
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
}
}
opts := [] iam . Option {
iam . WithName ( "Generated org scope" ),
iam . WithDescription ( "Provides an initial org scope in Boundary" ),
iam . WithRandomReader ( b . SecureRandomReader ),
iam . WithPublicId ( b . DevOrgId ),
}
orgScope , err := iam . NewOrg ( opts ... )
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
}
2020-09-24 12:54:40 -04:00
orgScope , err = iamRepo . CreateScope ( cancelCtx , orgScope , b . DevUserId , opts ... )
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 == "" {
b . DevProjectId , err = db . NewPublicId ( scope . Project . Prefix ())
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
}
}
opts = [] iam . Option {
iam . WithName ( "Generated project scope" ),
iam . WithDescription ( "Provides an initial project scope in Boundary" ),
iam . WithRandomReader ( b . SecureRandomReader ),
iam . WithPublicId ( b . DevProjectId ),
}
projScope , err := iam . NewProject ( b . DevOrgId , opts ... )
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
}
2020-09-24 12:54:40 -04:00
projScope , err = iamRepo . CreateScope ( cancelCtx , projScope , b . DevUserId , opts ... )
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 )
kmsRepo , err := kms . NewRepository ( rw , rw )
if err != nil {
2020-09-24 12:54:40 -04:00
return nil , nil , nil , fmt . Errorf ( "error creating kms repository: %w" , err )
2020-09-24 03:31:26 -04:00
}
kmsCache , err := kms . NewKms ( kmsRepo , kms . WithLogger ( b . Logger . Named ( "kms" )))
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 (
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
}
cancelCtx , cancel := context . WithCancel ( ctx )
2021-02-05 12:58:54 -07:00
defer cancel ()
2020-09-24 03:31:26 -04:00
go func () {
2021-02-05 12:58:54 -07:00
select {
case <- b . ShutdownCh :
cancel ()
case <- cancelCtx . Done ():
}
2020-09-24 03:31:26 -04:00
}()
staticRepo , err := static . NewRepository ( rw , rw , kmsCache )
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 == "" {
b . DevHostCatalogId , err = db . NewPublicId ( static . HostCatalogPrefix )
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" ),
static . WithDescription ( "Provides an initial host catalog in Boundary" ),
static . WithPublicId ( b . DevHostCatalogId ),
}
hc , err := static . NewHostCatalog ( b . DevProjectId , opts ... )
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
}
if hc , err = staticRepo . CreateCatalog ( cancelCtx , 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 == "" {
b . DevHostId , err = db . NewPublicId ( static . HostPrefix )
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" ),
static . WithDescription ( "Provides an initial host in Boundary" ),
static . WithAddress ( b . DevHostAddress ),
static . WithPublicId ( b . DevHostId ),
}
h , err := static . NewHost ( hc . PublicId , opts ... )
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
}
if h , err = staticRepo . CreateHost ( cancelCtx , 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 == "" {
b . DevHostSetId , err = db . NewPublicId ( static . HostSetPrefix )
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" ),
static . WithDescription ( "Provides an initial host set in Boundary" ),
static . WithPublicId ( b . DevHostSetId ),
}
hs , err := static . NewHostSet ( hc . PublicId , opts ... )
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
}
if hs , err = staticRepo . CreateSet ( cancelCtx , 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
if _ , err := staticRepo . AddSetMembers ( cancelCtx , 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
}
func ( b * Server ) CreateInitialTarget ( ctx context . Context ) ( target . Target , error ) {
rw := db . New ( b . Database )
kmsRepo , err := kms . NewRepository ( rw , rw )
if err != nil {
return nil , fmt . Errorf ( "error creating kms repository: %w" , err )
}
kmsCache , err := kms . NewKms ( kmsRepo , kms . WithLogger ( b . Logger . Named ( "kms" )))
if err != nil {
return nil , fmt . Errorf ( "error creating kms cache: %w" , err )
}
if err := kmsCache . AddExternalWrappers (
kms . WithRootWrapper ( b . RootKms ),
); err != nil {
return nil , fmt . Errorf ( "error adding config keys to kms: %w" , err )
}
cancelCtx , cancel := context . WithCancel ( ctx )
2021-02-05 12:58:54 -07:00
defer cancel ()
2020-09-24 03:31:26 -04:00
go func () {
2021-02-05 12:58:54 -07:00
select {
case <- b . ShutdownCh :
cancel ()
case <- cancelCtx . Done ():
}
2020-09-24 03:31:26 -04:00
}()
targetRepo , err := target . NewRepository ( rw , rw , kmsCache )
if err != nil {
return nil , fmt . Errorf ( "error creating target repository: %w" , err )
}
// Host Catalog
if b . DevTargetId == "" {
b . DevTargetId , err = db . NewPublicId ( target . TcpTargetPrefix )
if err != nil {
return nil , fmt . Errorf ( "error generating initial target id: %w" , err )
}
}
if b . DevTargetDefaultPort == 0 {
b . DevTargetDefaultPort = 22
}
opts := [] target . Option {
target . WithName ( "Generated target" ),
target . WithDescription ( "Provides an initial target in Boundary" ),
target . WithDefaultPort ( uint32 ( b . DevTargetDefaultPort )),
target . WithHostSets ([] string { b . DevHostSetId }),
2020-09-24 17:29:12 -04:00
target . WithSessionMaxSeconds ( uint32 ( b . DevTargetSessionMaxSeconds )),
target . WithSessionConnectionLimit ( int32 ( b . DevTargetSessionConnectionLimit )),
2020-09-24 03:31:26 -04:00
target . WithPublicId ( b . DevTargetId ),
}
t , err := target . NewTcpTarget ( b . DevProjectId , opts ... )
if err != nil {
return nil , fmt . Errorf ( "error creating in memory target: %w" , err )
}
2021-06-22 22:26:26 -04:00
tt , _ , _ , err := targetRepo . CreateTcpTarget ( cancelCtx , t , opts ... )
2020-09-24 03:31:26 -04:00
if err != nil {
return nil , fmt . Errorf ( "error saving target to the db: %w" , err )
}
b . InfoKeys = append ( b . InfoKeys , "generated target id" )
b . Info [ "generated target id" ] = b . DevTargetId
2021-02-11 13:14:18 -05:00
// If we have an unprivileged dev user, add user to the role that grants
2021-04-23 12:45:08 -05:00
// list/read:self/cancel:self on sessions, read:self/delete:self/list on
// tokens, and an authorize-session role
2021-02-11 13:14:18 -05:00
if b . DevUnprivilegedUserId != "" {
iamRepo , err := iam . NewRepository ( rw , rw , kmsCache , iam . WithRandomReader ( b . SecureRandomReader ))
if err != nil {
return nil , fmt . Errorf ( "unable to create repo for unprivileged user target connection role: %w" , err )
}
roles , err := iamRepo . ListRoles ( ctx , [] string { b . DevProjectId })
if err != nil {
return nil , fmt . Errorf ( "unable to list existing roles in project: %w" , err )
}
if len ( roles ) != 2 {
return nil , fmt . Errorf ( "unexpected number of roles in default project, expected 2, got %d" , len ( roles ))
}
var idx int = - 1
for i , r := range roles {
// Hacky, I know, but saves a DB trip to look up other
// characteristics like "if any principals are currently attached".
// No matter what we pick here it's a bit heuristical.
if r . Name == "Default Grants" {
idx = i
break
}
}
if idx == - 1 {
return nil , fmt . Errorf ( "couldn't find default grants role in default project" )
}
if _ , err := iamRepo . AddPrincipalRoles ( ctx ,
roles [ idx ]. PublicId ,
roles [ idx ]. Version ,
[] string { b . DevUnprivilegedUserId }); err != nil {
return nil , fmt . Errorf ( "error adding unpriv user ID to project default role: %w" , err )
}
pr , err := iam . NewRole ( b . DevProjectId ,
iam . WithName ( "Unprivileged User Session Authorization" ),
iam . WithDescription ( `Provides grants within the dev project scope to allow the initial unprivileged user to authorize sessions against the dev target` ),
)
if err != nil {
return nil , fmt . Errorf ( "error creating in memory role for generated grants: %w" , err )
}
sessionRole , err := iamRepo . CreateRole ( cancelCtx , pr )
if err != nil {
return nil , fmt . Errorf ( "error creating role for unprivileged user generated grants: %w" , err )
}
if _ , err := iamRepo . AddRoleGrants ( cancelCtx ,
sessionRole . PublicId ,
sessionRole . Version ,
[] string { fmt . Sprintf ( "id=%s;actions=authorize-session" , b . DevTargetId )},
); err != nil {
return nil , fmt . Errorf ( "error creating grant for unprivileged user generated grants: %w" , err )
}
if _ , err := iamRepo . AddPrincipalRoles ( cancelCtx , sessionRole . PublicId , sessionRole . Version + 1 , [] string { b . DevUnprivilegedUserId }, nil ); err != nil {
return nil , fmt . Errorf ( "error adding principal to role for unprivileged user generated grants: %w" , err )
}
}
2020-09-24 03:31:26 -04:00
return tt , nil
}