fix: segregate env setup
This commit is contained in:
parent
332269ecf9
commit
4e19f73845
|
@ -20,6 +20,8 @@ const (
|
||||||
EnvKeyAuthorizerURL = "AUTHORIZER_URL"
|
EnvKeyAuthorizerURL = "AUTHORIZER_URL"
|
||||||
// EnvKeyPort key for env variable PORT
|
// EnvKeyPort key for env variable PORT
|
||||||
EnvKeyPort = "PORT"
|
EnvKeyPort = "PORT"
|
||||||
|
// EnvKeyClientID key for env variable CLIENT_ID
|
||||||
|
EnvKeyClientID = "CLIENT_ID"
|
||||||
|
|
||||||
// EnvKeyAdminSecret key for env variable ADMIN_SECRET
|
// EnvKeyAdminSecret key for env variable ADMIN_SECRET
|
||||||
EnvKeyAdminSecret = "ADMIN_SECRET"
|
EnvKeyAdminSecret = "ADMIN_SECRET"
|
||||||
|
|
137
server/crypto/ecdsa.go
Normal file
137
server/crypto/ecdsa.go
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewECDSAKey to generate new ECDSA Key if env is not set
|
||||||
|
func NewECDSAKey() (*ecdsa.PrivateKey, string, string, error) {
|
||||||
|
key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey, publicKey, err := AsECDSAStr(key, &key.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, privateKey, publicKey, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsECDSA checks if given string is valid ECDSA algo
|
||||||
|
func IsECDSA(algo string) bool {
|
||||||
|
switch algo {
|
||||||
|
case "ES256", "ES384", "ES512":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportEcdsaPrivateKeyAsPemStr to get ECDSA private key as pem string
|
||||||
|
func ExportEcdsaPrivateKeyAsPemStr(privkey *ecdsa.PrivateKey) (string, error) {
|
||||||
|
privkeyBytes, err := x509.MarshalECPrivateKey(privkey)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
privkeyPem := pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: "ECDSA PRIVATE KEY",
|
||||||
|
Bytes: privkeyBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return string(privkeyPem), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportEcdsaPublicKeyAsPemStr to get ECDSA public key as pem string
|
||||||
|
func ExportEcdsaPublicKeyAsPemStr(pubkey *ecdsa.PublicKey) (string, error) {
|
||||||
|
pubkeyBytes, err := x509.MarshalPKIXPublicKey(pubkey)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
pubkeyPem := pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: "ECDSA PUBLIC KEY",
|
||||||
|
Bytes: pubkeyBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return string(pubkeyPem), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseEcdsaPrivateKeyFromPemStr to parse ECDSA private key from pem string
|
||||||
|
func ParseEcdsaPrivateKeyFromPemStr(privPEM string) (*ecdsa.PrivateKey, error) {
|
||||||
|
block, _ := pem.Decode([]byte(privPEM))
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("failed to parse PEM block containing the key")
|
||||||
|
}
|
||||||
|
|
||||||
|
priv, err := x509.ParseECPrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseEcdsaPublicKeyFromPemStr to parse ECDSA public key from pem string
|
||||||
|
func ParseEcdsaPublicKeyFromPemStr(pubPEM string) (*ecdsa.PublicKey, error) {
|
||||||
|
block, _ := pem.Decode([]byte(pubPEM))
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("failed to parse PEM block containing the key")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch pub := pub.(type) {
|
||||||
|
case *ecdsa.PublicKey:
|
||||||
|
return pub, nil
|
||||||
|
default:
|
||||||
|
break // fall through
|
||||||
|
}
|
||||||
|
return nil, errors.New("Key type is not ECDSA")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsECDSAStr returns private, public key string or error
|
||||||
|
func AsECDSAStr(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey) (string, string, error) {
|
||||||
|
// Export the keys to pem string
|
||||||
|
privPem, err := ExportEcdsaPrivateKeyAsPemStr(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
pubPem, err := ExportEcdsaPublicKeyAsPemStr(publicKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import the keys from pem string
|
||||||
|
privParsed, err := ParseEcdsaPrivateKeyFromPemStr(privPem)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
pubParsed, err := ParseEcdsaPublicKeyFromPemStr(pubPem)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export the newly imported keys
|
||||||
|
privParsedPem, err := ExportEcdsaPrivateKeyAsPemStr(privParsed)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
pubParsedPem, err := ExportEcdsaPublicKeyAsPemStr(pubParsed)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return privParsedPem, pubParsedPem, nil
|
||||||
|
}
|
19
server/crypto/hmac.go
Normal file
19
server/crypto/hmac.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import "github.com/google/uuid"
|
||||||
|
|
||||||
|
// NewHMAC key returns new key that can be used to ecnrypt data using HMAC algo
|
||||||
|
func NewHMACKey() string {
|
||||||
|
key := uuid.New().String()
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHMACValid checks if given string is valid HMCA algo
|
||||||
|
func IsHMACA(algo string) bool {
|
||||||
|
switch algo {
|
||||||
|
case "HS256", "HS384", "HS512":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
127
server/crypto/rsa.go
Normal file
127
server/crypto/rsa.go
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewRSAKey to generate new RSA Key if env is not set
|
||||||
|
func NewRSAKey() (*rsa.PrivateKey, string, string, error) {
|
||||||
|
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey, publicKey, err := AsRSAStr(key, &key.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, privateKey, publicKey, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRSA checks if given string is valid RSA algo
|
||||||
|
func IsRSA(algo string) bool {
|
||||||
|
switch algo {
|
||||||
|
case "RS256", "RS384", "RS512":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportRsaPrivateKeyAsPemStr to get RSA private key as pem string
|
||||||
|
func ExportRsaPrivateKeyAsPemStr(privkey *rsa.PrivateKey) string {
|
||||||
|
privkeyBytes := x509.MarshalPKCS1PrivateKey(privkey)
|
||||||
|
privkeyPem := pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: privkeyBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return string(privkeyPem)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportRsaPublicKeyAsPemStr to get RSA public key as pem string
|
||||||
|
func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) (string, error) {
|
||||||
|
pubkeyBytes, err := x509.MarshalPKIXPublicKey(pubkey)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
pubkeyPem := pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: "RSA PUBLIC KEY",
|
||||||
|
Bytes: pubkeyBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return string(pubkeyPem), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseRsaPrivateKeyFromPemStr to parse RSA private key from pem string
|
||||||
|
func ParseRsaPrivateKeyFromPemStr(privPEM string) (*rsa.PrivateKey, error) {
|
||||||
|
block, _ := pem.Decode([]byte(privPEM))
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("failed to parse PEM block containing the key")
|
||||||
|
}
|
||||||
|
|
||||||
|
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseRsaPublicKeyFromPemStr to parse RSA public key from pem string
|
||||||
|
func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {
|
||||||
|
block, _ := pem.Decode([]byte(pubPEM))
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("failed to parse PEM block containing the key")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch pub := pub.(type) {
|
||||||
|
case *rsa.PublicKey:
|
||||||
|
return pub, nil
|
||||||
|
default:
|
||||||
|
break // fall through
|
||||||
|
}
|
||||||
|
return nil, errors.New("Key type is not RSA")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsRSAStr returns private, public key string or error
|
||||||
|
func AsRSAStr(privateKey *rsa.PrivateKey, publickKey *rsa.PublicKey) (string, string, error) {
|
||||||
|
// Export the keys to pem string
|
||||||
|
privPem := ExportRsaPrivateKeyAsPemStr(privateKey)
|
||||||
|
pubPem, err := ExportRsaPublicKeyAsPemStr(publickKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import the keys from pem string
|
||||||
|
privParsed, err := ParseRsaPrivateKeyFromPemStr(privPem)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
pubParsed, err := ParseRsaPublicKeyFromPemStr(pubPem)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export the newly imported keys
|
||||||
|
privParsedPem := ExportRsaPrivateKeyAsPemStr(privParsed)
|
||||||
|
pubParsedPem, err := ExportRsaPublicKeyAsPemStr(pubParsed)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return privParsedPem, pubParsedPem, nil
|
||||||
|
}
|
205
server/env/env.go
vendored
205
server/env/env.go
vendored
|
@ -1,22 +1,80 @@
|
||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// InitRequiredEnv to initialize EnvData and through error if required env are not present
|
||||||
|
func InitRequiredEnv() {
|
||||||
|
envPath := os.Getenv(constants.EnvKeyEnvPath)
|
||||||
|
|
||||||
|
if envPath == "" {
|
||||||
|
envPath = `.env`
|
||||||
|
}
|
||||||
|
|
||||||
|
if envstore.ARG_ENV_FILE != nil && *envstore.ARG_ENV_FILE != "" {
|
||||||
|
envPath = *envstore.ARG_ENV_FILE
|
||||||
|
}
|
||||||
|
|
||||||
|
err := godotenv.Load(envPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("using OS env instead of %s file", envPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
dbURL := os.Getenv(constants.EnvKeyDatabaseURL)
|
||||||
|
dbType := os.Getenv(constants.EnvKeyDatabaseType)
|
||||||
|
dbName := os.Getenv(constants.EnvKeyDatabaseName)
|
||||||
|
|
||||||
|
if dbType == "" {
|
||||||
|
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
|
||||||
|
dbType = *envstore.ARG_DB_TYPE
|
||||||
|
}
|
||||||
|
|
||||||
|
if dbType == "" {
|
||||||
|
panic("DATABASE_TYPE is required")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dbURL == "" {
|
||||||
|
if envstore.ARG_DB_URL != nil && *envstore.ARG_DB_URL != "" {
|
||||||
|
dbURL = *envstore.ARG_DB_URL
|
||||||
|
}
|
||||||
|
|
||||||
|
if dbURL == "" {
|
||||||
|
panic("DATABASE_URL is required")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dbName == "" {
|
||||||
|
if dbName == "" {
|
||||||
|
dbName = "authorizer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, envPath)
|
||||||
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
|
||||||
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
|
||||||
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseName, dbName)
|
||||||
|
}
|
||||||
|
|
||||||
// InitEnv to initialize EnvData and through error if required env are not present
|
// InitEnv to initialize EnvData and through error if required env are not present
|
||||||
func InitEnv() {
|
func InitAllEnv() {
|
||||||
// get clone of current store
|
envData, err := GetEnvData()
|
||||||
envData := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
if err != nil {
|
||||||
|
log.Println("No env data found in db, using local clone of env data")
|
||||||
|
// get clone of current store
|
||||||
|
envData = envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
||||||
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyEnv] == "" {
|
if envData.StringEnv[constants.EnvKeyEnv] == "" {
|
||||||
envData.StringEnv[constants.EnvKeyEnv] = os.Getenv(constants.EnvKeyEnv)
|
envData.StringEnv[constants.EnvKeyEnv] = os.Getenv(constants.EnvKeyEnv)
|
||||||
|
@ -36,19 +94,6 @@ func InitEnv() {
|
||||||
envData.StringEnv[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL)
|
envData.StringEnv[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyEnvPath] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyEnvPath] = `.env`
|
|
||||||
}
|
|
||||||
|
|
||||||
if envstore.ARG_ENV_FILE != nil && *envstore.ARG_ENV_FILE != "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyEnvPath] = *envstore.ARG_ENV_FILE
|
|
||||||
}
|
|
||||||
|
|
||||||
err := godotenv.Load(envData.StringEnv[constants.EnvKeyEnvPath])
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("using OS env instead of %s file", envData.StringEnv[constants.EnvKeyEnvPath])
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyPort] == "" {
|
if envData.StringEnv[constants.EnvKeyPort] == "" {
|
||||||
envData.StringEnv[constants.EnvKeyPort] = os.Getenv(constants.EnvKeyPort)
|
envData.StringEnv[constants.EnvKeyPort] = os.Getenv(constants.EnvKeyPort)
|
||||||
if envData.StringEnv[constants.EnvKeyPort] == "" {
|
if envData.StringEnv[constants.EnvKeyPort] == "" {
|
||||||
|
@ -60,37 +105,6 @@ func InitEnv() {
|
||||||
envData.StringEnv[constants.EnvKeyAdminSecret] = os.Getenv(constants.EnvKeyAdminSecret)
|
envData.StringEnv[constants.EnvKeyAdminSecret] = os.Getenv(constants.EnvKeyAdminSecret)
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseType] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseType] = os.Getenv(constants.EnvKeyDatabaseType)
|
|
||||||
|
|
||||||
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseType] = *envstore.ARG_DB_TYPE
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseType] == "" {
|
|
||||||
panic("DATABASE_TYPE is required")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseURL] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseURL] = os.Getenv(constants.EnvKeyDatabaseURL)
|
|
||||||
|
|
||||||
if envstore.ARG_DB_URL != nil && *envstore.ARG_DB_URL != "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseURL] = *envstore.ARG_DB_URL
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseURL] == "" {
|
|
||||||
panic("DATABASE_URL is required")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseName] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseName] = os.Getenv(constants.EnvKeyDatabaseName)
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseName] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseName] = "authorizer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeySmtpHost] == "" {
|
if envData.StringEnv[constants.EnvKeySmtpHost] == "" {
|
||||||
envData.StringEnv[constants.EnvKeySmtpHost] = os.Getenv(constants.EnvKeySmtpHost)
|
envData.StringEnv[constants.EnvKeySmtpHost] = os.Getenv(constants.EnvKeySmtpHost)
|
||||||
}
|
}
|
||||||
|
@ -111,32 +125,83 @@ func InitEnv() {
|
||||||
envData.StringEnv[constants.EnvKeySenderEmail] = os.Getenv(constants.EnvKeySenderEmail)
|
envData.StringEnv[constants.EnvKeySenderEmail] = os.Getenv(constants.EnvKeySenderEmail)
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
algo := ""
|
||||||
envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv(constants.EnvKeyJwtSecret)
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyJwtSecret] = uuid.New().String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyCustomAccessTokenScript] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyCustomAccessTokenScript] = os.Getenv(constants.EnvKeyCustomAccessTokenScript)
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtPrivateKey] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyJwtPrivateKey] = os.Getenv(constants.EnvKeyJwtPrivateKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtPublicKey] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyJwtPublicKey] = os.Getenv(constants.EnvKeyJwtPublicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
||||||
envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv(constants.EnvKeyJwtType)
|
envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv(constants.EnvKeyJwtType)
|
||||||
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
||||||
envData.StringEnv[constants.EnvKeyJwtType] = "HS256"
|
envData.StringEnv[constants.EnvKeyJwtType] = "RS256"
|
||||||
|
algo = envData.StringEnv[constants.EnvKeyJwtType]
|
||||||
|
} else {
|
||||||
|
algo = envData.StringEnv[constants.EnvKeyJwtType]
|
||||||
|
if !crypto.IsHMACA(algo) && !crypto.IsRSA(algo) && !crypto.IsECDSA(algo) {
|
||||||
|
panic("JWT_TYPE is invalid")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" && crypto.IsHMACA(algo) {
|
||||||
|
envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv(constants.EnvKeyJwtSecret)
|
||||||
|
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
||||||
|
envData.StringEnv[constants.EnvKeyJwtSecret] = crypto.NewHMACKey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if crypto.IsRSA(algo) || crypto.IsECDSA(algo) {
|
||||||
|
privateKey, publicKey := "", ""
|
||||||
|
|
||||||
|
if envData.StringEnv[constants.EnvKeyJwtPrivateKey] == "" {
|
||||||
|
privateKey = os.Getenv(constants.EnvKeyJwtPrivateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
if envData.StringEnv[constants.EnvKeyJwtPublicKey] == "" {
|
||||||
|
publicKey = os.Getenv(constants.EnvKeyJwtPublicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if algo is RSA / ECDSA, then we need to have both private and public key
|
||||||
|
// if either of them is not present generate new keys
|
||||||
|
if privateKey == "" || publicKey == "" {
|
||||||
|
if crypto.IsRSA(algo) {
|
||||||
|
_, privateKey, publicKey, err = crypto.NewRSAKey()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else if crypto.IsECDSA(algo) {
|
||||||
|
_, privateKey, publicKey, err = crypto.NewECDSAKey()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// parse keys to make sure they are valid
|
||||||
|
if crypto.IsRSA(algo) {
|
||||||
|
_, err = crypto.ParseRsaPrivateKeyFromPemStr(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = crypto.ParseRsaPublicKeyFromPemStr(publicKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else if crypto.IsECDSA(algo) {
|
||||||
|
_, err = crypto.ParseEcdsaPrivateKeyFromPemStr(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = crypto.ParseEcdsaPublicKeyFromPemStr(publicKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("=> keys parsed successfully")
|
||||||
|
}
|
||||||
|
fmt.Println(privateKey)
|
||||||
|
fmt.Println(publicKey)
|
||||||
|
envData.StringEnv[constants.EnvKeyJwtPrivateKey] = privateKey
|
||||||
|
envData.StringEnv[constants.EnvKeyJwtPublicKey] = publicKey
|
||||||
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" {
|
if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" {
|
||||||
envData.StringEnv[constants.EnvKeyJwtRoleClaim] = os.Getenv(constants.EnvKeyJwtRoleClaim)
|
envData.StringEnv[constants.EnvKeyJwtRoleClaim] = os.Getenv(constants.EnvKeyJwtRoleClaim)
|
||||||
|
|
||||||
|
@ -145,6 +210,10 @@ func InitEnv() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if envData.StringEnv[constants.EnvKeyCustomAccessTokenScript] == "" {
|
||||||
|
envData.StringEnv[constants.EnvKeyCustomAccessTokenScript] = os.Getenv(constants.EnvKeyCustomAccessTokenScript)
|
||||||
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyRedisURL] == "" {
|
if envData.StringEnv[constants.EnvKeyRedisURL] == "" {
|
||||||
envData.StringEnv[constants.EnvKeyRedisURL] = os.Getenv(constants.EnvKeyRedisURL)
|
envData.StringEnv[constants.EnvKeyRedisURL] = os.Getenv(constants.EnvKeyRedisURL)
|
||||||
}
|
}
|
||||||
|
|
54
server/env/persist_env.go
vendored
54
server/env/persist_env.go
vendored
|
@ -15,6 +15,40 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetEnvData returns the env data from database
|
||||||
|
func GetEnvData() (envstore.Store, error) {
|
||||||
|
var result envstore.Store
|
||||||
|
env, err := db.Provider.GetEnv()
|
||||||
|
// config not found in db
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptionKey := env.Hash
|
||||||
|
decryptedEncryptionKey, err := utils.DecryptB64(encryptionKey)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
|
||||||
|
b64DecryptedConfig, err := utils.DecryptB64(env.EnvData)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptedConfigs, err := utils.DecryptAES([]byte(b64DecryptedConfig))
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(decryptedConfigs, &result)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
// PersistEnv persists the environment variables to the database
|
// PersistEnv persists the environment variables to the database
|
||||||
func PersistEnv() error {
|
func PersistEnv() error {
|
||||||
env, err := db.Provider.GetEnv()
|
env, err := db.Provider.GetEnv()
|
||||||
|
@ -29,22 +63,16 @@ func PersistEnv() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// configData, err := json.Marshal()
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// encryptedConfig, err := utils.EncryptAES(configData)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
env = models.Env{
|
env = models.Env{
|
||||||
Hash: encodedHash,
|
Hash: encodedHash,
|
||||||
EnvData: encryptedConfig,
|
EnvData: encryptedConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Provider.AddEnv(env)
|
env, err = db.Provider.AddEnv(env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// decrypt the config data from db
|
// decrypt the config data from db
|
||||||
// decryption can be done using the hash stored in db
|
// decryption can be done using the hash stored in db
|
||||||
|
@ -134,6 +162,7 @@ func PersistEnv() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvStore(storeData)
|
envstore.EnvInMemoryStoreObj.UpdateEnvStore(storeData)
|
||||||
|
|
||||||
if hasChanged {
|
if hasChanged {
|
||||||
encryptedConfig, err := utils.EncryptEnvData(storeData)
|
encryptedConfig, err := utils.EncryptEnvData(storeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -147,8 +176,11 @@ func PersistEnv() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ID of env is used to identify the config and declared as client id
|
||||||
|
// this client id can be used in `aud` section of JWT token
|
||||||
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyClientID, env.ID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
@ -22,13 +23,20 @@ func main() {
|
||||||
|
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyVersion, VERSION)
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyVersion, VERSION)
|
||||||
|
|
||||||
env.InitEnv()
|
// initialize required envs (mainly db env & env file path)
|
||||||
|
env.InitRequiredEnv()
|
||||||
|
// initialize db provider
|
||||||
db.InitDB()
|
db.InitDB()
|
||||||
env.PersistEnv()
|
// initialize all envs
|
||||||
|
env.InitAllEnv()
|
||||||
|
// persist all envs
|
||||||
|
err := env.PersistEnv()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error persisting env:", err)
|
||||||
|
}
|
||||||
|
|
||||||
sessionstore.InitSession()
|
sessionstore.InitSession()
|
||||||
oauth.InitOAuth()
|
oauth.InitOAuth()
|
||||||
|
|
||||||
router := routes.InitRouter()
|
router := routes.InitRouter()
|
||||||
|
|
||||||
router.Run(":" + envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyPort))
|
router.Run(":" + envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyPort))
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
func TestEnvs(t *testing.T) {
|
func TestEnvs(t *testing.T) {
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, "../../.env.sample")
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, "../../.env.sample")
|
||||||
env.InitEnv()
|
env.InitAllEnv()
|
||||||
store := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
store := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
||||||
|
|
||||||
assert.Equal(t, store.StringEnv[constants.EnvKeyEnv], "production")
|
assert.Equal(t, store.StringEnv[constants.EnvKeyEnv], "production")
|
||||||
|
|
|
@ -78,7 +78,7 @@ func testSetup() TestSetup {
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPassword, "test")
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPassword, "test")
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySenderEmail, "info@yopmail.com")
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySenderEmail, "info@yopmail.com")
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyProtectedRoles, []string{"admin"})
|
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyProtectedRoles, []string{"admin"})
|
||||||
env.InitEnv()
|
env.InitAllEnv()
|
||||||
sessionstore.InitSession()
|
sessionstore.InitSession()
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user