diff --git a/cmd/security-bootstrapper/entrypoint-scripts/postgres_wait_install.sh b/cmd/security-bootstrapper/entrypoint-scripts/postgres_wait_install.sh index eb6d09914c..81787168a6 100755 --- a/cmd/security-bootstrapper/entrypoint-scripts/postgres_wait_install.sh +++ b/cmd/security-bootstrapper/entrypoint-scripts/postgres_wait_install.sh @@ -21,29 +21,34 @@ set -e # env settings are populated from env files of docker-compose -echo "Script for waiting security bootstrapping on Postgres" - -# gating on the TokensReadyPort -echo "$(date) Executing waitFor on Postgres with waiting on TokensReadyPort \ - tcp://${STAGEGATE_SECRETSTORESETUP_HOST}:${STAGEGATE_SECRETSTORESETUP_TOKENS_READYPORT}" -/edgex-init/security-bootstrapper --configDir=/edgex-init/res waitFor \ - -uri tcp://"${STAGEGATE_SECRETSTORESETUP_HOST}":"${STAGEGATE_SECRETSTORESETUP_TOKENS_READYPORT}" \ - -timeout "${STAGEGATE_WAITFOR_TIMEOUT}" - -# the configurePostgres retrieves the postgres user's credentials from secretstore (i.e. Vault) -echo "$(date) ${STAGEGATE_SECRETSTORESETUP_HOST} tokens ready, bootstrapping postgres..." -/edgex-init/security-bootstrapper --configDir=/edgex-init/bootstrap-postgres/res configurePostgres - -postgres_bootstrapping_status=$? -if [ $postgres_bootstrapping_status -ne 0 ]; then - echo "$(date) failed to bootstrap postgres" - exit 1 -fi +# execute security-bootstrapper scripts only with root user +if [ "$(id -u)" = '0' ]; then + # gating on the TokensReadyPort + echo "$(date) Executing waitFor on Postgres with waiting on TokensReadyPort \ + tcp://${STAGEGATE_SECRETSTORESETUP_HOST}:${STAGEGATE_SECRETSTORESETUP_TOKENS_READYPORT}" + /edgex-init/security-bootstrapper --configDir=/edgex-init/res waitFor \ + -uri tcp://"${STAGEGATE_SECRETSTORESETUP_HOST}":"${STAGEGATE_SECRETSTORESETUP_TOKENS_READYPORT}" \ + -timeout "${STAGEGATE_WAITFOR_TIMEOUT}" + + # the configurePostgres retrieves the postgres user's credentials from secretstore (i.e. Vault) + echo "$(date) ${STAGEGATE_SECRETSTORESETUP_HOST} tokens ready, bootstrapping postgres..." + + /edgex-init/security-bootstrapper --configDir=/edgex-init/bootstrap-postgres/res configurePostgres + + postgres_bootstrapping_status=$? + + if [ $postgres_bootstrapping_status -ne 0 ]; then + echo "$(date) failed to bootstrap postgres" + exit 1 + fi -if [ ! -f "${DATABASECONFIG_PATH}"/"${DATABASECONFIG_NAME}" ]; then - ehco "$(date) Error: initialization script file ${DATABASECONFIG_PATH}/${DATABASECONFIG_NAME} not exists" - exit 1 + if [ ! -f "${DATABASECONFIG_PATH}"/"${DATABASECONFIG_NAME}" ]; then + ehco "$(date) Error: initialization script file ${DATABASECONFIG_PATH}/${DATABASECONFIG_NAME} not exists" + exit 1 + fi + find "${DATABASECONFIG_PATH}" \! -user postgres -exec chown postgres '{}' + + chmod 700 "${DATABASECONFIG_PATH}" fi # customizing of Postgres startup process by including the docker-entrypoint script diff --git a/internal/security/bootstrapper/helper/postgres_script.go b/internal/security/bootstrapper/helper/postgres_script.go index eb8c2ce476..945daea979 100644 --- a/internal/security/bootstrapper/helper/postgres_script.go +++ b/internal/security/bootstrapper/helper/postgres_script.go @@ -33,7 +33,7 @@ set -e psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -q <<-'EOSQL' SELECT 'CREATE DATABASE edgex_db' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'edgex_db')\gexec - CREATE GROUP edgex_user; + SELECT 'CREATE GROUP edgex_user' WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'edgex_user') \gexec GRANT CONNECT, CREATE ON DATABASE edgex_db TO edgex_user; \connect edgex_db; @@ -41,9 +41,11 @@ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -q <<-'EOSQL' BEGIN {{range .Services}} CREATE SCHEMA IF NOT EXISTS {{.Username}}; - CREATE USER {{.Username}} with PASSWORD '{{.Password}}'; - GRANT ALL ON SCHEMA {{.Username}} TO {{.Username}}; - ALTER GROUP edgex_user ADD USER {{.Username}}; + IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '{{.Username}}') THEN + CREATE USER {{.Username}} with PASSWORD '{{.Password}}'; + GRANT ALL ON SCHEMA {{.Username}} TO {{.Username}}; + ALTER GROUP edgex_user ADD USER {{.Username}}; + END IF; {{end}} END $$; EOSQL` diff --git a/internal/security/bootstrapper/helper/postgres_script_test.go b/internal/security/bootstrapper/helper/postgres_script_test.go index d7d0b7ba34..bd86a13fe2 100644 --- a/internal/security/bootstrapper/helper/postgres_script_test.go +++ b/internal/security/bootstrapper/helper/postgres_script_test.go @@ -24,7 +24,7 @@ func TestGeneratePostgresScript(t *testing.T) { _ = os.RemoveAll(fileName) }() - mockUsername := "core-data" + mockUsername := "core_data" mockPassword := "password123" mockCredMap := []map[string]any{{ "Username": mockUsername, @@ -50,6 +50,6 @@ func TestGeneratePostgresScript(t *testing.T) { } expectedCreateScript := fmt.Sprintf("CREATE USER %s with PASSWORD '%s';", mockUsername, mockPassword) - require.Equal(t, 15, len(outputlines)) - require.Equal(t, expectedCreateScript, strings.TrimSpace(outputlines[10])) + require.Equal(t, 17, len(outputlines)) + require.Equal(t, expectedCreateScript, strings.TrimSpace(outputlines[11])) } diff --git a/internal/security/secretstore/init.go b/internal/security/secretstore/init.go index f5f31977b2..98a0ce09ae 100644 --- a/internal/security/secretstore/init.go +++ b/internal/security/secretstore/init.go @@ -426,40 +426,41 @@ func (b *Bootstrap) BootstrapHandler(ctx context.Context, _ *sync.WaitGroup, _ s if err != nil { return false } - } else { - // Add any additional services that need the known DB secret - lc.Infof("adding any additional services using redisdb for knownSecrets...") - services, ok := knownSecretsToAdd[redisSecretName] - if ok { - for _, service := range services { - err = addServiceCredential(lc, redisSecretName, secretStore, service, redisCredentials) - if err != nil { - lc.Error(err.Error()) - return false - } + } + + // NOTE: for now redis secrets will be generated for all database types + // Add any additional services that need the known DB secret + lc.Infof("adding any additional services using redisdb for knownSecrets...") + services, ok := knownSecretsToAdd[redisSecretName] + if ok { + for _, service := range services { + err = addServiceCredential(lc, redisSecretName, secretStore, service, redisCredentials) + if err != nil { + lc.Error(err.Error()) + return false } } + } - lc.Infof("adding redisdb secret name for internal services...") - for _, info := range configuration.Databases { - service := info.Service + lc.Infof("adding redisdb secret name for internal services...") + for _, info := range configuration.Databases { + service := info.Service - // add credentials to service path if specified and they're not already there - if len(service) != 0 { - err = addServiceCredential(lc, redisSecretName, secretStore, service, redisCredentials) - if err != nil { - lc.Error(err.Error()) - return false - } + // add credentials to service path if specified and they're not already there + if len(service) != 0 { + err = addServiceCredential(lc, redisSecretName, secretStore, service, redisCredentials) + if err != nil { + lc.Error(err.Error()) + return false } } - // security-bootstrapper-redis uses the path /v1/secret/edgex/security-bootstrapper-redis/ and go-mod-bootstrap - // with append the DB type (redisdb) - err = storeCredential(lc, "security-bootstrapper-redis", secretStore, redisSecretName, redisCredentials) - if err != nil { - lc.Error(err.Error()) - return false - } + } + // security-bootstrapper-redis uses the path /v1/secret/edgex/security-bootstrapper-redis/ and go-mod-bootstrap + // with append the DB type (redisdb) + err = storeCredential(lc, "security-bootstrapper-redis", secretStore, redisSecretName, redisCredentials) + if err != nil { + lc.Error(err.Error()) + return false } // for secure message bus creds