mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
NOISSUE - Vault operations with app role authentication (#2084)
Signed-off-by: Arvindh <arvindh91@gmail.com> Signed-off-by: arvindh123 <arvindh91@gmail.com>
This commit is contained in:
+41
-36
@@ -30,38 +30,41 @@ curl -s -S -X DELETE http://localhost:9019/certs/revoke -H "Authorization: Beare
|
||||
|
||||
The service is configured using the environment variables presented in the following table. Note that any unset variables will be replaced with their default values.
|
||||
|
||||
| Variable | Description | Default |
|
||||
| ------------------------- | --------------------------------------------------------------------------- | ----------------------------------- |
|
||||
| MG_CERTS_LOG_LEVEL | Log level for the Certs (debug, info, warn, error) | info |
|
||||
| MG_CERTS_HTTP_HOST | Service Certs host | "" |
|
||||
| MG_CERTS_HTTP_PORT | Service Certs port | 9019 |
|
||||
| MG_CERTS_HTTP_SERVER_CERT | Path to the PEM encoded server certificate file | "" |
|
||||
| MG_CERTS_HTTP_SERVER_KEY | Path to the PEM encoded server key file | "" |
|
||||
| MG_AUTH_GRPC_URL | Auth service gRPC URL | <localhost:8181> |
|
||||
| MG_AUTH_GRPC_TIMEOUT | Auth service gRPC request timeout in seconds | 1s |
|
||||
| MG_AUTH_GRPC_CLIENT_CERT | Path to the PEM encoded auth service gRPC client certificate file | "" |
|
||||
| MG_AUTH_GRPC_CLIENT_KEY | Path to the PEM encoded auth service gRPC client key file | "" |
|
||||
| MG_AUTH_GRPC_SERVER_CERTS | Path to the PEM encoded auth server gRPC server trusted CA certificate file | "" |
|
||||
| MG_CERTS_SIGN_CA_PATH | Path to the PEM encoded CA certificate file | ca.crt |
|
||||
| MG_CERTS_SIGN_CA_KEY_PATH | Path to the PEM encoded CA key file | ca.key |
|
||||
| MG_CERTS_VAULT_HOST | Vault host | "" |
|
||||
| MG_VAULT_PKI_INT_PATH | Vault PKI intermediate path | pki_int |
|
||||
| MG_VAULT_CA_ROLE_NAME | Vault PKI role name | magistrala |
|
||||
| MG_VAULT_TOKEN | Vault token | "" |
|
||||
| MG_CERTS_DB_HOST | Database host | localhost |
|
||||
| MG_CERTS_DB_PORT | Database port | 5432 |
|
||||
| MG_CERTS_DB_PASS | Database password | magistrala |
|
||||
| MG_CERTS_DB_USER | Database user | magistrala |
|
||||
| MG_CERTS_DB_NAME | Database name | certs |
|
||||
| MG_CERTS_DB_SSL_MODE | Database SSL mode | disable |
|
||||
| MG_CERTS_DB_SSL_CERT | Database SSL certificate | "" |
|
||||
| MG_CERTS_DB_SSL_KEY | Database SSL key | "" |
|
||||
| MG_CERTS_DB_SSL_ROOT_CERT | Database SSL root certificate | "" |
|
||||
| MG_THINGS_URL | Things service URL | <localhost:9000> |
|
||||
| MG_JAEGER_URL | Jaeger server URL | <http://localhost:14268/api/traces> |
|
||||
| MG_JAEGER_TRACE_RATIO | Jaeger sampling ratio | 1.0 |
|
||||
| MG_SEND_TELEMETRY | Send telemetry to magistrala call home server | true |
|
||||
| MG_CERTS_INSTANCE_ID | Service instance ID | "" |
|
||||
|
||||
| Variable | Description | Default |
|
||||
| :---------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
||||
| MG_CERTS_LOG_LEVEL | Log level for the Certs (debug, info, warn, error) | info |
|
||||
| MG_CERTS_HTTP_HOST | Service Certs host | "" |
|
||||
| MG_CERTS_HTTP_PORT | Service Certs port | 9019 |
|
||||
| MG_CERTS_HTTP_SERVER_CERT | Path to the PEM encoded server certificate file | "" |
|
||||
| MG_CERTS_HTTP_SERVER_KEY | Path to the PEM encoded server key file | "" |
|
||||
| MG_AUTH_GRPC_URL | Auth service gRPC URL | [localhost:8181](localhost:8181) |
|
||||
| MG_AUTH_GRPC_TIMEOUT | Auth service gRPC request timeout in seconds | 1s |
|
||||
| MG_AUTH_GRPC_CLIENT_CERT | Path to the PEM encoded auth service gRPC client certificate file | "" |
|
||||
| MG_AUTH_GRPC_CLIENT_KEY | Path to the PEM encoded auth service gRPC client key file | "" |
|
||||
| MG_AUTH_GRPC_SERVER_CERTS | Path to the PEM encoded auth server gRPC server trusted CA certificate file | "" |
|
||||
| MG_CERTS_SIGN_CA_PATH | Path to the PEM encoded CA certificate file | ca.crt |
|
||||
| MG_CERTS_SIGN_CA_KEY_PATH | Path to the PEM encoded CA key file | ca.key |
|
||||
| MG_CERTS_VAULT_HOST | Vault host | http://vault:8200 |
|
||||
| MG_CERTS_VAULT_NAMESPACE | Vault namespace in which pki is present | magistrala |
|
||||
| MG_CERTS_VAULT_APPROLE_ROLEID | Vault AppRole auth RoleID | magistrala |
|
||||
| MG_CERTS_VAULT_APPROLE_SECRET | Vault AppRole auth Secret | magistrala |
|
||||
| MG_CERTS_VAULT_THINGS_CERTS_PKI_PATH | Vault PKI path for issuing Things Certificates | pki_int |
|
||||
| MG_CERTS_VAULT_THINGS_CERTS_PKI_ROLE_NAME | Vault PKI Role Name for issuing Things Certificates | magistrala_things_certs |
|
||||
| MG_CERTS_DB_HOST | Database host | localhost |
|
||||
| MG_CERTS_DB_PORT | Database port | 5432 |
|
||||
| MG_CERTS_DB_PASS | Database password | magistrala |
|
||||
| MG_CERTS_DB_USER | Database user | magistrala |
|
||||
| MG_CERTS_DB_NAME | Database name | certs |
|
||||
| MG_CERTS_DB_SSL_MODE | Database SSL mode | disable |
|
||||
| MG_CERTS_DB_SSL_CERT | Database SSL certificate | "" |
|
||||
| MG_CERTS_DB_SSL_KEY | Database SSL key | "" |
|
||||
| MG_CERTS_DB_SSL_ROOT_CERT | Database SSL root certificate | "" |
|
||||
| MG_THINGS_URL | Things service URL | [localhost:9000](localhost:9000) |
|
||||
| MG_JAEGER_URL | Jaeger server URL | [http://localhost:14268/api/traces](http://localhost:14268/api/traces) |
|
||||
| MG_JAEGER_TRACE_RATIO | Jaeger sampling ratio | 1.0 |
|
||||
| MG_SEND_TELEMETRY | Send telemetry to magistrala call home server | true |
|
||||
| MG_CERTS_INSTANCE_ID | Service instance ID | "" |
|
||||
|
||||
## Deployment
|
||||
|
||||
@@ -95,10 +98,12 @@ MG_AUTH_GRPC_CLIENT_KEY="" \
|
||||
MG_AUTH_GRPC_SERVER_CERTS="" \
|
||||
MG_CERTS_SIGN_CA_PATH=ca.crt \
|
||||
MG_CERTS_SIGN_CA_KEY_PATH=ca.key \
|
||||
MG_CERTS_VAULT_HOST="" \
|
||||
MG_VAULT_PKI_INT_PATH=pki_int \
|
||||
MG_VAULT_CA_ROLE_NAME=magistrala \
|
||||
MG_VAULT_TOKEN="" \
|
||||
MG_CERTS_VAULT_HOST=http://vault:8200 \
|
||||
MG_CERTS_VAULT_NAMESPACE=magistrala \
|
||||
MG_CERTS_VAULT_APPROLE_ROLEID=magistrala \
|
||||
MG_CERTS_VAULT_APPROLE_SECRET=magistrala \
|
||||
MG_CERTS_VAULT_THINGS_CERTS_PKI_PATH=pki_int \
|
||||
MG_CERTS_VAULT_THINGS_CERTS_PKI_ROLE_NAME=magistrala_things_certs \
|
||||
MG_CERTS_DB_HOST=localhost \
|
||||
MG_CERTS_DB_PORT=5432 \
|
||||
MG_CERTS_DB_PASS=magistrala \
|
||||
|
||||
@@ -6,6 +6,7 @@ package mocks
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
@@ -160,6 +161,10 @@ func (a *agent) Revoke(serial string) (time.Time, error) {
|
||||
return time.Now(), nil
|
||||
}
|
||||
|
||||
func (a *agent) LoginAndRenew(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func publicKey(priv interface{}) (interface{}, error) {
|
||||
if priv == nil {
|
||||
return nil, errPrivateKeyEmpty
|
||||
|
||||
+105
-4
@@ -5,11 +5,14 @@
|
||||
package pki
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/api/auth/approle"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
@@ -30,6 +33,13 @@ var (
|
||||
ErrFailedCertRevocation = errors.New("failed to revoke certificate")
|
||||
|
||||
errFailedCertDecoding = errors.New("failed to decode response from vault service")
|
||||
errFailedToLogin = errors.New("failed to login to Vault")
|
||||
errFailedAppRole = errors.New("failed to create vault new app role")
|
||||
errNoAuthInfo = errors.New("no auth information from Vault")
|
||||
errNonRenewal = errors.New("token is not configured to be renewable")
|
||||
errRenewWatcher = errors.New("unable to initialize new lifetime watcher for renewing auth token")
|
||||
errFailedRenew = errors.New("failed to renew token")
|
||||
errCouldNotRenew = errors.New("token can no longer be renewed")
|
||||
)
|
||||
|
||||
type Cert struct {
|
||||
@@ -52,10 +62,15 @@ type Agent interface {
|
||||
|
||||
// Revoke revokes certificate from PKI
|
||||
Revoke(serial string) (time.Time, error)
|
||||
|
||||
// Login to PKI and renews token
|
||||
LoginAndRenew(ctx context.Context) error
|
||||
}
|
||||
|
||||
type pkiAgent struct {
|
||||
token string
|
||||
appRole string
|
||||
appSecret string
|
||||
namespace string
|
||||
path string
|
||||
role string
|
||||
host string
|
||||
@@ -63,6 +78,8 @@ type pkiAgent struct {
|
||||
readURL string
|
||||
revokeURL string
|
||||
client *api.Client
|
||||
secret *api.Secret
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
type certReq struct {
|
||||
@@ -75,7 +92,7 @@ type certRevokeReq struct {
|
||||
}
|
||||
|
||||
// NewVaultClient instantiates a Vault client.
|
||||
func NewVaultClient(token, host, path, role string) (Agent, error) {
|
||||
func NewVaultClient(appRole, appSecret, host, namespace, path, role string, logger *slog.Logger) (Agent, error) {
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = host
|
||||
|
||||
@@ -83,13 +100,19 @@ func NewVaultClient(token, host, path, role string) (Agent, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.SetToken(token)
|
||||
if namespace != "" {
|
||||
client.SetNamespace(namespace)
|
||||
}
|
||||
|
||||
p := pkiAgent{
|
||||
token: token,
|
||||
appRole: appRole,
|
||||
appSecret: appSecret,
|
||||
host: host,
|
||||
namespace: namespace,
|
||||
role: role,
|
||||
path: path,
|
||||
client: client,
|
||||
logger: logger,
|
||||
issueURL: "/" + path + "/" + issue + "/" + role,
|
||||
readURL: "/" + path + "/" + cert + "/",
|
||||
revokeURL: "/" + path + "/" + revoke,
|
||||
@@ -162,3 +185,81 @@ func (p *pkiAgent) Revoke(serial string) (time.Time, error) {
|
||||
|
||||
return time.Unix(0, int64(rev)*int64(time.Second)), nil
|
||||
}
|
||||
|
||||
func (p *pkiAgent) LoginAndRenew(ctx context.Context) error {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
p.logger.Info("pki login and renew function stopping")
|
||||
return nil
|
||||
default:
|
||||
err := p.login(ctx)
|
||||
if err != nil {
|
||||
p.logger.Info("unable to authenticate to Vault", slog.Any("error", err))
|
||||
time.Sleep(5 * time.Second)
|
||||
break
|
||||
}
|
||||
tokenErr := p.manageTokenLifecycle()
|
||||
if tokenErr != nil {
|
||||
p.logger.Info("unable to start managing token lifecycle", slog.Any("error", tokenErr))
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pkiAgent) login(ctx context.Context) error {
|
||||
secretID := &approle.SecretID{FromString: p.appSecret}
|
||||
|
||||
authMethod, err := approle.NewAppRoleAuth(
|
||||
p.appRole,
|
||||
secretID,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(errFailedAppRole, err)
|
||||
}
|
||||
if p.namespace != "" {
|
||||
p.client.SetNamespace(p.namespace)
|
||||
}
|
||||
secret, err := p.client.Auth().Login(ctx, authMethod)
|
||||
if err != nil {
|
||||
return errors.Wrap(errFailedToLogin, err)
|
||||
}
|
||||
if secret == nil {
|
||||
return errNoAuthInfo
|
||||
}
|
||||
p.secret = secret
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pkiAgent) manageTokenLifecycle() error {
|
||||
renew := p.secret.Auth.Renewable
|
||||
if !renew {
|
||||
return errNonRenewal
|
||||
}
|
||||
|
||||
watcher, err := p.client.NewLifetimeWatcher(&api.LifetimeWatcherInput{
|
||||
Secret: p.secret,
|
||||
Increment: 3600, // Requesting token for 3600s = 1h, If this is more than token_max_ttl, then response token will have token_max_ttl
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(errRenewWatcher, err)
|
||||
}
|
||||
|
||||
go watcher.Start()
|
||||
defer watcher.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case err := <-watcher.DoneCh():
|
||||
if err != nil {
|
||||
return errors.Wrap(errFailedRenew, err)
|
||||
}
|
||||
// This occurs once the token has reached max TTL or if token is disabled for renewal.
|
||||
return errCouldNotRenew
|
||||
|
||||
case renewal := <-watcher.RenewCh():
|
||||
p.logger.Info("Successfully renewed token", slog.Any("renewed_at", renewal.RenewedAt))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-5
@@ -57,10 +57,12 @@ type config struct {
|
||||
SignCAKeyPath string `env:"MG_CERTS_SIGN_CA_KEY_PATH" envDefault:"ca.key"`
|
||||
|
||||
// 3rd party PKI API access settings
|
||||
PkiHost string `env:"MG_CERTS_VAULT_HOST" envDefault:""`
|
||||
PkiPath string `env:"MG_VAULT_PKI_INT_PATH" envDefault:"pki_int"`
|
||||
PkiRole string `env:"MG_VAULT_CA_ROLE_NAME" envDefault:"magistrala"`
|
||||
PkiToken string `env:"MG_VAULT_TOKEN" envDefault:""`
|
||||
PkiHost string `env:"MG_CERTS_VAULT_HOST" envDefault:""`
|
||||
PkiAppRoleID string `env:"MG_CERTS_VAULT_APPROLE_ROLEID" envDefault:""`
|
||||
PkiAppSecret string `env:"MG_CERTS_VAULT_APPROLE_SECRET" envDefault:""`
|
||||
PkiNamespace string `env:"MG_CERTS_VAULT_NAMESPACE" envDefault:""`
|
||||
PkiPath string `env:"MG_CERTS_VAULT_THINGS_CERTS_PKI_PATH" envDefault:"pki_int"`
|
||||
PkiRole string `env:"MG_CERTS_VAULT_THINGS_CERTS_PKI_ROLE_NAME" envDefault:"magistrala"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -94,13 +96,17 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
pkiclient, err := vault.NewVaultClient(cfg.PkiToken, cfg.PkiHost, cfg.PkiPath, cfg.PkiRole)
|
||||
pkiclient, err := vault.NewVaultClient(cfg.PkiAppRoleID, cfg.PkiAppSecret, cfg.PkiHost, cfg.PkiNamespace, cfg.PkiPath, cfg.PkiRole, logger)
|
||||
if err != nil {
|
||||
logger.Error("failed to configure client for PKI engine")
|
||||
exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
g.Go(func() error {
|
||||
return pkiclient.LoginAndRenew(ctx)
|
||||
})
|
||||
|
||||
dbConfig := pgclient.Config{Name: defDB}
|
||||
if err := env.ParseWithOptions(&dbConfig, env.Options{Prefix: envPrefixDB}); err != nil {
|
||||
logger.Error(err.Error())
|
||||
|
||||
+48
-19
@@ -311,13 +311,58 @@ MG_PROVISION_CERTS_HOURS_VALID=2400h
|
||||
MG_PROVISION_CERTS_RSA_BITS=2048
|
||||
MG_PROVISION_INSTANCE_ID=
|
||||
|
||||
### Vault
|
||||
MG_VAULT_HOST=vault
|
||||
MG_VAULT_PORT=8200
|
||||
MG_VAULT_ADDR=http://vault:8200
|
||||
MG_VAULT_NAMESPACE=magistrala
|
||||
MG_VAULT_UNSEAL_KEY_1=
|
||||
MG_VAULT_UNSEAL_KEY_2=
|
||||
MG_VAULT_UNSEAL_KEY_3=
|
||||
MG_VAULT_TOKEN=
|
||||
|
||||
MG_VAULT_PKI_PATH=pki
|
||||
MG_VAULT_PKI_ROLE_NAME=magistrala_int_ca
|
||||
MG_VAULT_PKI_FILE_NAME=mg_root
|
||||
MG_VAULT_PKI_CA_CN='Magistrala Root Certificate Authority'
|
||||
MG_VAULT_PKI_CA_OU='Magistrala'
|
||||
MG_VAULT_PKI_CA_O='Magistrala'
|
||||
MG_VAULT_PKI_CA_C='FRANCE'
|
||||
MG_VAULT_PKI_CA_L='PARIS'
|
||||
MG_VAULT_PKI_CA_ST='PARIS'
|
||||
MG_VAULT_PKI_CA_ADDR='5 Av. Anatole'
|
||||
MG_VAULT_PKI_CA_PO='75007'
|
||||
MG_VAULT_PKI_CLUSTER_PATH=http://localhost
|
||||
MG_VAULT_PKI_CLUSTER_AIA_PATH=http://localhost
|
||||
|
||||
MG_VAULT_PKI_INT_PATH=pki_int
|
||||
MG_VAULT_PKI_INT_SERVER_CERTS_ROLE_NAME=magistrala_server_certs
|
||||
MG_VAULT_PKI_INT_THINGS_CERTS_ROLE_NAME=magistrala_things_certs
|
||||
MG_VAULT_PKI_INT_FILE_NAME=mg_int
|
||||
MG_VAULT_PKI_INT_CA_CN='Magistrala Intermediate Certificate Authority'
|
||||
MG_VAULT_PKI_INT_CA_OU='Magistrala'
|
||||
MG_VAULT_PKI_INT_CA_O='Magistrala'
|
||||
MG_VAULT_PKI_INT_CA_C='FRANCE'
|
||||
MG_VAULT_PKI_INT_CA_L='PARIS'
|
||||
MG_VAULT_PKI_INT_CA_ST='PARIS'
|
||||
MG_VAULT_PKI_INT_CA_ADDR='5 Av. Anatole'
|
||||
MG_VAULT_PKI_INT_CA_PO='75007'
|
||||
MG_VAULT_PKI_INT_CLUSTER_PATH=http://localhost
|
||||
MG_VAULT_PKI_INT_CLUSTER_AIA_PATH=http://localhost
|
||||
|
||||
MG_VAULT_THINGS_CERTS_ISSUER_ROLEID=magistrala
|
||||
MG_VAULT_THINGS_CERTS_ISSUER_SECRET=magistrala
|
||||
|
||||
# Certs
|
||||
MG_CERTS_LOG_LEVEL=debug
|
||||
MG_CERTS_SIGN_CA_PATH=/etc/ssl/certs/ca.crt
|
||||
MG_CERTS_SIGN_CA_KEY_PATH=/etc/ssl/certs/ca.key
|
||||
MG_CERTS_VAULT_HOST=http://vault:8200
|
||||
MG_VAULT_PKI_INT_PATH=pki_int
|
||||
MG_VAULT_CA_ROLE_NAME=magistrala
|
||||
MG_CERTS_VAULT_HOST=${MG_VAULT_ADDR}
|
||||
MG_CERTS_VAULT_NAMESPACE=${MG_VAULT_NAMESPACE}
|
||||
MG_CERTS_VAULT_APPROLE_ROLEID=${MG_VAULT_THINGS_CERTS_ISSUER_ROLEID}
|
||||
MG_CERTS_VAULT_APPROLE_SECRET=${MG_VAULT_THINGS_CERTS_ISSUER_SECRET}
|
||||
MG_CERTS_VAULT_THINGS_CERTS_PKI_PATH=${MG_VAULT_PKI_INT_PATH}
|
||||
MG_CERTS_VAULT_THINGS_CERTS_PKI_ROLE_NAME=${MG_VAULT_PKI_INT_THINGS_CERTS_ROLE_NAME}
|
||||
MG_CERTS_HTTP_HOST=certs
|
||||
MG_CERTS_HTTP_PORT=9019
|
||||
MG_CERTS_HTTP_SERVER_CERT=
|
||||
@@ -333,22 +378,6 @@ MG_CERTS_DB_SSL_KEY=
|
||||
MG_CERTS_DB_SSL_ROOT_CERT=
|
||||
MG_CERTS_INSTANCE_ID=
|
||||
|
||||
### Vault
|
||||
MG_VAULT_HOST=vault
|
||||
MG_VAULT_PORT=8200
|
||||
MG_VAULT_UNSEAL_KEY_1=
|
||||
MG_VAULT_UNSEAL_KEY_2=
|
||||
MG_VAULT_UNSEAL_KEY_3=
|
||||
MG_VAULT_TOKEN=
|
||||
MG_VAULT_CA_NAME=magistrala
|
||||
MG_VAULT_CA_ROLE_NAME=magistrala
|
||||
MG_VAULT_PKI_PATH=pki
|
||||
MG_VAULT_PKI_INT_PATH=pki_int
|
||||
MG_VAULT_CA_CN=magistrala.com
|
||||
MG_VAULT_CA_OU='Magistrala Cloud'
|
||||
MG_VAULT_CA_O='Magistrala Labs'
|
||||
MG_VAULT_CA_C=Serbia
|
||||
MG_VAULT_CA_L=Belgrade
|
||||
|
||||
### LoRa
|
||||
MG_LORA_ADAPTER_LOG_LEVEL=debug
|
||||
|
||||
@@ -117,3 +117,18 @@ services:
|
||||
volumes:
|
||||
- magistrala-broker-volume:/data
|
||||
```
|
||||
|
||||
## Nginx Configuration
|
||||
|
||||
Nginx is the entry point for all traffic to Magistrala.
|
||||
By using environment variables file at `docker/.env` you can modify the below given Nginx directive.
|
||||
|
||||
`MG_NGINX_SERVER_NAME` environmental variable is used to configure nginx directive `server_name`. If environmental variable `MG_NGINX_SERVER_NAME` is empty then default value `localhost` will set to `server_name`.
|
||||
|
||||
`MG_NGINX_SERVER_CERT` environmental variable is used to configure nginx directive `ssl_certificate`. If environmental variable `MG_NGINX_SERVER_CERT` is empty then by default server certificate in the path `docker/ssl/certs/magistrala-server.crt` will be assigned.
|
||||
|
||||
`MG_NGINX_SERVER_KEY` environmental variable is used to configure nginx directive `ssl_certificate_key`. If environmental variable `MG_NGINX_SERVER_KEY` is empty then by default server certificate key in the path `docker/ssl/certs/magistrala-server.key` will be assigned.
|
||||
|
||||
`MG_NGINX_SERVER_CLIENT_CA` environmental variable is used to configure nginx directive `ssl_client_certificate`. If environmental variable `MG_NGINX_SERVER_CLIENT_CA` is empty then by default certificate in the path `docker/ssl/certs/ca.crt` will be assigned.
|
||||
|
||||
`MG_NGINX_SERVER_DHPARAM` environmental variable is used to configure nginx directive `ssl_dhparam`. If environmental variable `MG_NGINX_SERVER_DHPARAM` is empty then by default file in the path `docker/ssl/dhparam.pem` will be assigned.
|
||||
|
||||
@@ -44,10 +44,11 @@ services:
|
||||
MG_CERTS_SIGN_CA_PATH: ${MG_CERTS_SIGN_CA_PATH}
|
||||
MG_CERTS_SIGN_CA_KEY_PATH: ${MG_CERTS_SIGN_CA_KEY_PATH}
|
||||
MG_CERTS_VAULT_HOST: ${MG_CERTS_VAULT_HOST}
|
||||
MG_VAULT_PKI_INT_PATH: ${MG_VAULT_PKI_INT_PATH}
|
||||
MG_VAULT_CA_ROLE_NAME: ${MG_VAULT_CA_ROLE_NAME}
|
||||
MG_VAULT_PKI_PATH: ${MG_VAULT_PKI_PATH}
|
||||
MG_VAULT_TOKEN: ${MG_VAULT_TOKEN}
|
||||
MG_CERTS_VAULT_NAMESPACE: ${MG_CERTS_VAULT_NAMESPACE}
|
||||
MG_CERTS_VAULT_APPROLE_ROLEID: ${MG_CERTS_VAULT_APPROLE_ROLEID}
|
||||
MG_CERTS_VAULT_APPROLE_SECRET: ${MG_CERTS_VAULT_APPROLE_SECRET}
|
||||
MG_CERTS_VAULT_THINGS_CERTS_PKI_PATH: ${MG_CERTS_VAULT_THINGS_CERTS_PKI_PATH}
|
||||
MG_CERTS_VAULT_THINGS_CERTS_PKI_ROLE_NAME: ${MG_CERTS_VAULT_THINGS_CERTS_PKI_ROLE_NAME}
|
||||
MG_CERTS_HTTP_HOST: ${MG_CERTS_HTTP_HOST}
|
||||
MG_CERTS_HTTP_PORT: ${MG_CERTS_HTTP_PORT}
|
||||
MG_CERTS_HTTP_SERVER_CERT: ${MG_CERTS_HTTP_SERVER_CERT}
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
data
|
||||
magistrala_things_certs_issue.hcl
|
||||
|
||||
@@ -6,35 +6,53 @@ When the Vault service is started, some initialization steps need to be done to
|
||||
|
||||
## Configuration
|
||||
|
||||
| Variable | Description | Default |
|
||||
| --------------------- | ------------------------------------------------------- | ---------------- |
|
||||
| MG_VAULT_HOST | Vault service address | vault |
|
||||
| MG_VAULT_PORT | Vault service port | 8200 |
|
||||
| MG_VAULT_UNSEAL_KEY_1 | Vault unseal key | "" |
|
||||
| MG_VAULT_UNSEAL_KEY_2 | Vault unseal key | "" |
|
||||
| MG_VAULT_UNSEAL_KEY_3 | Vault unseal key | "" |
|
||||
| MG_VAULT_TOKEN | Vault cli access token | "" |
|
||||
| MG_VAULT_PKI_PATH | Vault secrets engine path for CA | pki |
|
||||
| MG_VAULT_PKI_INT_PATH | Vault secrets engine path for intermediate CA | pki_int |
|
||||
| MG_VAULT_CA_ROLE_NAME | Vault secrets engine role | magistrala |
|
||||
| MG_VAULT_CA_NAME | Certificates name used by `vault-set-pki.sh` | magistrala |
|
||||
| MG_VAULT_CA_CN | Common name used for CA creation by `vault-set-pki.sh` | magistrala.com |
|
||||
| MG_VAULT_CA_OU | Org unit used for CA creation by `vault-set-pki.sh` | Magistrala Cloud |
|
||||
| MG_VAULT_CA_O | Organization used for CA creation by `vault-set-pki.sh` | Magistrala Labs |
|
||||
| MG_VAULT_CA_C | Country used for CA creation by `vault-set-pki.sh` | Serbia |
|
||||
| MG_VAULT_CA_L | Location used for CA creation by `vault-set-pki.sh` | Belgrade |
|
||||
|
||||
| Variable | Description | Default |
|
||||
| :---------------------------------------- | ------------------------------------------------------------------------------- | --------------------------------------- |
|
||||
| MG_VAULT_HOST | Vault service address | vault |
|
||||
| MG_VAULT_PORT | Vault service port | 8200 |
|
||||
| MG_VAULT_ADDR | Vault Address | http://vault:8200 |
|
||||
| MG_VAULT_UNSEAL_KEY_1 | Vault unseal key | "" |
|
||||
| MG_VAULT_UNSEAL_KEY_2 | Vault unseal key | "" |
|
||||
| MG_VAULT_UNSEAL_KEY_3 | Vault unseal key | "" |
|
||||
| MG_VAULT_TOKEN | Vault cli access token | "" |
|
||||
| MG_VAULT_PKI_PATH | Vault secrets engine path for Root CA | pki |
|
||||
| MG_VAULT_PKI_ROLE_NAME | Vault Root CA role name to issue intermediate CA | magistrala_int_ca |
|
||||
| MG_VAULT_PKI_FILE_NAME | Root CA Certificates name used by`vault_set_pki.sh` | mg_root |
|
||||
| MG_VAULT_PKI_CA_CN | Common name used for Root CA creation by`vault_set_pki.sh` | Magistrala Root Certificate Authority |
|
||||
| MG_VAULT_PKI_CA_OU | Organization unit used for Root CA creation by`vault_set_pki.sh` | Magistrala |
|
||||
| MG_VAULT_PKI_CA_O | Organization used for Root CA creation by`vault_set_pki.sh` | Magistrala |
|
||||
| MG_VAULT_PKI_CA_C | Country used for Root CA creation by`vault_set_pki.sh` | FRANCE |
|
||||
| MG_VAULT_PKI_CA_L | Location used for Root CA creation by`vault_set_pki.sh` | PARIS |
|
||||
| MG_VAULT_PKI_CA_ST | State or Provisions used for Root CA creation by`vault_set_pki.sh` | PARIS |
|
||||
| MG_VAULT_PKI_CA_ADDR | Address used for Root CA creation by`vault_set_pki.sh` | 5 Av. Anatole |
|
||||
| MG_VAULT_PKI_CA_PO | Postal code used for Root CA creation by`vault_set_pki.sh` | 75007 |
|
||||
| MG_VAULT_PKI_CLUSTER_PATH | Vault Root CA Cluster Path | http://localhost |
|
||||
| MG_VAULT_PKI_CLUSTER_AIA_PATH | Vault Root CA Cluster AIA Path | http://localhost |
|
||||
| MG_VAULT_PKI_INT_PATH | Vault secrets engine path for Intermediate CA | pki_int |
|
||||
| MG_VAULT_PKI_INT_SERVER_CERTS_ROLE_NAME | Vault Intermediate CA role name to issue server certificate | magistrala_server_certs |
|
||||
| MG_VAULT_PKI_INT_THINGS_CERTS_ROLE_NAME | Vault Intermediate CA role name to issue Things certificates | magistrala_things_certs |
|
||||
| MG_VAULT_PKI_INT_FILE_NAME | Intermediate CA Certificates name used by`vault_set_pki.sh` | mg_root |
|
||||
| MG_VAULT_PKI_INT_CA_CN | Common name used for Intermediate CA creation by`vault_set_pki.sh` | Magistrala Root Certificate Authority |
|
||||
| MG_VAULT_PKI_INT_CA_OU | Organization unit used for Root CA creation by`vault_set_pki.sh` | Magistrala |
|
||||
| MG_VAULT_PKI_INT_CA_O | Organization used for Intermediate CA creation by`vault_set_pki.sh` | Magistrala |
|
||||
| MG_VAULT_PKI_INT_CA_C | Country used for Intermediate CA creation by`vault_set_pki.sh` | FRANCE |
|
||||
| MG_VAULT_PKI_INT_CA_L | Location used for Intermediate CA creation by`vault_set_pki.sh` | PARIS |
|
||||
| MG_VAULT_PKI_INT_CA_ST | State or Provisions used for Intermediate CA creation by`vault_set_pki.sh` | PARIS |
|
||||
| MG_VAULT_PKI_INT_CA_ADDR | Address used for Intermediate CA creation by`vault_set_pki.sh` | 5 Av. Anatole |
|
||||
| MG_VAULT_PKI_INT_CA_PO | Postal code used for Intermediate CA creation by`vault_set_pki.sh` | 75007 |
|
||||
| MG_VAULT_PKI_INT_CLUSTER_PATH | Vault Intermediate CA Cluster Path | http://localhost |
|
||||
| MG_VAULT_PKI_INT_CLUSTER_AIA_PATH | Vault Intermediate CA Cluster AIA Path | http://localhost |
|
||||
| MG_VAULT_THINGS_CERTS_ISSUER_ROLEID | Vault Intermediate CA Things Certificate issuer AppRole authentication RoleID | magistrala |
|
||||
| MG_VAULT_THINGS_CERTS_ISSUER_SECRET | Vault Intermediate CA Things Certificate issuer AppRole authentication Secret | magistrala |
|
||||
|
||||
## Setup
|
||||
|
||||
The following scripts are provided, which work on the running Vault service in Docker.
|
||||
|
||||
1. `vault-init.sh`
|
||||
### 1. `vault_init.sh`
|
||||
|
||||
Calls `vault operator init` to perform the initial vault initialization and generates
|
||||
a `data/secrets` file which contains the Vault unseal keys and root tokens.
|
||||
|
||||
After this step, the corresponding Vault environment variables (`MG_VAULT_TOKEN`, `MG_VAULT_UNSEAL_KEY_1`,
|
||||
`MG_VAULT_UNSEAL_KEY_2`, `MG_VAULT_UNSEAL_KEY_3`) should be updated in `.env` file.
|
||||
Calls `vault operator init` to perform the initial vault initialization and generates a `docker/addons/vault/data/secrets` file which contains the Vault unseal keys and root tokens.
|
||||
|
||||
Example contents for `data/secrets`:
|
||||
|
||||
@@ -62,23 +80,43 @@ bash-4.4
|
||||
Use 3 out of five keys presented and put it into .env file and than start the composition again Vault should be in unsealed state ( take a note that this is not recommended in terms of security, this is deployment for development) A real production deployment can use Vault auto unseal mode where vault gets unseal keys from some 3rd party KMS ( on AWS for example)
|
||||
```
|
||||
|
||||
2. `vault-unseal.sh`
|
||||
### 2. `vault_copy_env.sh`
|
||||
|
||||
After first step, the corresponding Vault environment variables (`MG_VAULT_TOKEN`, `MG_VAULT_UNSEAL_KEY_1`, `MG_VAULT_UNSEAL_KEY_2`, `MG_VAULT_UNSEAL_KEY_3`) should be updated in `.env` file.
|
||||
|
||||
`vault_copy_env.sh` scripts copies values from `docker/addons/vault/data/secrets` file and update environmental variables `MG_VAULT_TOKEN`, `MG_VAULT_UNSEAL_KEY_1`, `MG_VAULT_UNSEAL_KEY_2`, `MG_VAULT_UNSEAL_KEY_3` present in `.env` file.
|
||||
|
||||
### 3. `vault_unseal.sh`
|
||||
|
||||
This can be run after the initialization to unseal Vault, which is necessary for it to be used to store and/or get secrets.
|
||||
|
||||
This can be used if you don't want to restart the service.
|
||||
|
||||
The unseal environment variables need to be set in `.env` for the script to work (`MG_VAULT_TOKEN`, `MG_VAULT_UNSEAL_KEY_1`,
|
||||
`MG_VAULT_UNSEAL_KEY_2`, `MG_VAULT_UNSEAL_KEY_3`).
|
||||
The unseal environment variables need to be set in `.env` for the script to work (`MG_VAULT_TOKEN`,`MG_VAULT_UNSEAL_KEY_1`, `MG_VAULT_UNSEAL_KEY_2`, `MG_VAULT_UNSEAL_KEY_3`).
|
||||
|
||||
This script should not be necessary to run after the initial setup, since the Vault service unseals itself when
|
||||
starting the container.
|
||||
This script should not be necessary to run after the initial setup, since the Vault service unseals itself when starting the container.
|
||||
|
||||
3. `vault-set-pki.sh`
|
||||
### 4. `vault_set_pki.sh`
|
||||
|
||||
This script is used to generate the root certificate, intermediate certificate and HTTPS server certificate.
|
||||
After it runs, it copies the necessary certificates and keys to the `docker/ssl/certs` folder.
|
||||
This script is used to generate the root certificate, intermediate certificate and HTTPS server certificate.
|
||||
All generate certificates, keys and CSR by `vault_set_pki.sh` will be present at `docker/addons/vault/data`.
|
||||
|
||||
The CA parameters are obtained from the environment variables starting with `MG_VAULT_CA` in `.env` file.
|
||||
The parameters required for generating certificate are obtained from the environment variables which are loaded from `docker/.env`.
|
||||
|
||||
Environmental variables starting with `MG_VAULT_PKI` in `docker/.env` file are used by `vault_set_pki.sh` to generate root CA.
|
||||
Environmental variables starting with`MG_VAULT_PKI_INT` in `docker/.env` file are used by `vault_set_pki.sh` to generate intermediate CA.
|
||||
|
||||
### 5. `vault_create_approle.sh`
|
||||
|
||||
This script is used to enable app role authorization in Vault. Certs service used the approle credentials to issue, revoke things certificate from vault intermedate CA.
|
||||
|
||||
`vault_create_approle.sh` script by default tries to enable auth approle.
|
||||
If approle is already enabled in vault, then use args `skip_enable_app_role` to skip enable auth approle step.
|
||||
To skip enable auth approle step use the following `vault_create_approle.sh skip_enable_app_role`
|
||||
|
||||
### 6. `vault_copy_certs.sh`
|
||||
|
||||
This scripts copies the necessary certificates and keys from `docker/addons/vault/data` to the `docker/ssl/certs` folder.
|
||||
|
||||
## Vault CLI
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
# Allow issue certificate with role with default issuer from Intermediate PKI
|
||||
path "${MG_VAULT_PKI_INT_PATH}/issue/${MG_VAULT_PKI_INT_THINGS_CERTS_ROLE_NAME}" {
|
||||
capabilities = ["create", "update"]
|
||||
}
|
||||
|
||||
## Revole certificate from Intermediate PKI
|
||||
path "${MG_VAULT_PKI_INT_PATH}/revoke" {
|
||||
capabilities = ["create", "update"]
|
||||
}
|
||||
|
||||
## List Revoked Certificates from Intermediate PKI
|
||||
path "${MG_VAULT_PKI_INT_PATH}/certs/revoked" {
|
||||
capabilities = ["list"]
|
||||
}
|
||||
|
||||
|
||||
## List Certificates from Intermediate PKI
|
||||
path "${MG_VAULT_PKI_INT_PATH}/certs" {
|
||||
capabilities = ["list"]
|
||||
}
|
||||
|
||||
## Read Certificate from Intermediate PKI
|
||||
path "${MG_VAULT_PKI_INT_PATH}/cert/+" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "${MG_VAULT_PKI_INT_PATH}/cert/+/raw" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "${MG_VAULT_PKI_INT_PATH}/cert/+/raw/pem" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
export MAGISTRALA_DIR=$scriptdir/../../../
|
||||
|
||||
cd $scriptdir
|
||||
|
||||
readDotEnv() {
|
||||
set -o allexport
|
||||
source $MAGISTRALA_DIR/docker/.env
|
||||
set +o allexport
|
||||
}
|
||||
|
||||
vault() {
|
||||
docker exec -it magistrala-vault vault "$@"
|
||||
}
|
||||
|
||||
vaultEnablePKI() {
|
||||
vault secrets enable -path ${MG_VAULT_PKI_PATH} pki
|
||||
vault secrets tune -max-lease-ttl=87600h ${MG_VAULT_PKI_PATH}
|
||||
}
|
||||
|
||||
vaultAddRoleToSecret() {
|
||||
vault write ${MG_VAULT_PKI_PATH}/roles/${MG_VAULT_CA_NAME} \
|
||||
allow_any_name=true \
|
||||
max_ttl="4300h" \
|
||||
default_ttl="4300h" \
|
||||
generate_lease=true
|
||||
}
|
||||
|
||||
vaultGenerateRootCACertificate() {
|
||||
echo "Generate root CA certificate"
|
||||
vault write -format=json ${MG_VAULT_PKI_PATH}/root/generate/exported \
|
||||
common_name="\"$MG_VAULT_CA_CN CA Root\"" \
|
||||
ou="\"$MG_VAULT_CA_OU\""\
|
||||
organization="\"$MG_VAULT_CA_O\"" \
|
||||
country="\"$MG_VAULT_CA_C\"" \
|
||||
locality="\"$MG_VAULT_CA_L\"" \
|
||||
ttl=87600h | tee >(jq -r .data.certificate >data/${MG_VAULT_CA_NAME}_ca.crt) \
|
||||
>(jq -r .data.issuing_ca >data/${MG_VAULT_CA_NAME}_issuing_ca.crt) \
|
||||
>(jq -r .data.private_key >data/${MG_VAULT_CA_NAME}_ca.key)
|
||||
}
|
||||
|
||||
vaultGenerateIntermediateCAPKI() {
|
||||
echo "Generate Intermediate CA PKI"
|
||||
vault secrets enable -path=${MG_VAULT_PKI_INT_PATH} pki
|
||||
vault secrets tune -max-lease-ttl=43800h ${MG_VAULT_PKI_INT_PATH}
|
||||
}
|
||||
|
||||
vaultGenerateIntermediateCSR() {
|
||||
echo "Generate intermediate CSR"
|
||||
vault write -format=json ${MG_VAULT_PKI_INT_PATH}/intermediate/generate/exported \
|
||||
common_name="$MG_VAULT_CA_CN Intermediate Authority" \
|
||||
| tee >(jq -r .data.csr >data/${MG_VAULT_CA_NAME}_int.csr) \
|
||||
>(jq -r .data.private_key >data/${MG_VAULT_CA_NAME}_int.key)
|
||||
}
|
||||
|
||||
vaultSignIntermediateCSR() {
|
||||
echo "Sign intermediate CSR"
|
||||
docker cp data/${MG_VAULT_CA_NAME}_int.csr magistrala-vault:/vault/${MG_VAULT_CA_NAME}_int.csr
|
||||
vault write -format=json ${MG_VAULT_PKI_PATH}/root/sign-intermediate \
|
||||
csr=@/vault/${MG_VAULT_CA_NAME}_int.csr \
|
||||
| tee >(jq -r .data.certificate >data/${MG_VAULT_CA_NAME}_int.crt) \
|
||||
>(jq -r .data.issuing_ca >data/${MG_VAULT_CA_NAME}_int_issuing_ca.crt)
|
||||
}
|
||||
|
||||
vaultInjectIntermediateCertificate() {
|
||||
echo "Inject Intermediate Certificate"
|
||||
docker cp data/${MG_VAULT_CA_NAME}_int.crt magistrala-vault:/vault/${MG_VAULT_CA_NAME}_int.crt
|
||||
vault write ${MG_VAULT_PKI_INT_PATH}/intermediate/set-signed certificate=@/vault/${MG_VAULT_CA_NAME}_int.crt
|
||||
}
|
||||
|
||||
vaultGenerateIntermediateCertificateBundle() {
|
||||
echo "Generate intermediate certificate bundle"
|
||||
cat data/${MG_VAULT_CA_NAME}_int.crt data/${MG_VAULT_CA_NAME}_ca.crt \
|
||||
> data/${MG_VAULT_CA_NAME}_int_bundle.crt
|
||||
}
|
||||
|
||||
vaultSetupIssuingURLs() {
|
||||
echo "Setup URLs for CRL and issuing"
|
||||
VAULT_ADDR=http://$MG_VAULT_HOST:$MG_VAULT_PORT
|
||||
vault write ${MG_VAULT_PKI_INT_PATH}/config/urls \
|
||||
issuing_certificates="$VAULT_ADDR/v1/${MG_VAULT_PKI_INT_PATH}/ca" \
|
||||
crl_distribution_points="$VAULT_ADDR/v1/${MG_VAULT_PKI_INT_PATH}/crl"
|
||||
}
|
||||
|
||||
vaultSetupCARole() {
|
||||
echo "Setup CA role"
|
||||
vault write ${MG_VAULT_PKI_INT_PATH}/roles/${MG_VAULT_CA_ROLE_NAME} \
|
||||
allow_subdomains=true \
|
||||
allow_any_name=true \
|
||||
max_ttl="720h"
|
||||
}
|
||||
|
||||
vaultGenerateServerCertificate() {
|
||||
echo "Generate server certificate"
|
||||
vault write -format=json ${MG_VAULT_PKI_INT_PATH}/issue/${MG_VAULT_CA_ROLE_NAME} \
|
||||
common_name="$MG_VAULT_CA_CN" ttl="8670h" \
|
||||
| tee >(jq -r .data.certificate >data/${MG_VAULT_CA_CN}.crt) \
|
||||
>(jq -r .data.private_key >data/${MG_VAULT_CA_CN}.key)
|
||||
}
|
||||
|
||||
vaultCleanupFiles() {
|
||||
docker exec magistrala-vault sh -c 'rm -rf /vault/*.{crt,csr}'
|
||||
}
|
||||
|
||||
if ! command -v jq &> /dev/null
|
||||
then
|
||||
echo "jq command could not be found, please install it and try again."
|
||||
exit
|
||||
fi
|
||||
|
||||
readDotEnv
|
||||
|
||||
mkdir -p data
|
||||
|
||||
vault login ${MG_VAULT_TOKEN}
|
||||
|
||||
vaultEnablePKI
|
||||
vaultAddRoleToSecret
|
||||
vaultGenerateRootCACertificate
|
||||
vaultGenerateIntermediateCAPKI
|
||||
vaultGenerateIntermediateCSR
|
||||
vaultSignIntermediateCSR
|
||||
vaultInjectIntermediateCertificate
|
||||
vaultGenerateIntermediateCertificateBundle
|
||||
vaultSetupIssuingURLs
|
||||
vaultSetupCARole
|
||||
vaultGenerateServerCertificate
|
||||
vaultCleanupFiles
|
||||
|
||||
echo "Copying certificate files"
|
||||
|
||||
cp -v data/${MG_VAULT_CA_CN}.crt ${MAGISTRALA_DIR}/docker/ssl/certs/magistrala-server.crt
|
||||
cp -v data/${MG_VAULT_CA_CN}.key ${MAGISTRALA_DIR}/docker/ssl/certs/magistrala-server.key
|
||||
cp -v data/${MG_VAULT_CA_NAME}_int.key ${MAGISTRALA_DIR}/docker/ssl/certs/ca.key
|
||||
cp -v data/${MG_VAULT_CA_NAME}_int.crt ${MAGISTRALA_DIR}/docker/ssl/certs/ca.crt
|
||||
cp -v data/${MG_VAULT_CA_NAME}_int_bundle.crt ${MAGISTRALA_DIR}/docker/ssl/bundle.pem
|
||||
|
||||
exit 0
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/bash
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
export MAGISTRALA_DIR=$scriptdir/../../../
|
||||
|
||||
cd $scriptdir
|
||||
|
||||
readDotEnv() {
|
||||
set -o allexport
|
||||
source $MAGISTRALA_DIR/docker/.env
|
||||
set +o allexport
|
||||
}
|
||||
|
||||
readDotEnv
|
||||
|
||||
server_name="localhost"
|
||||
|
||||
# Check if MG_NGINX_SERVER_NAME is set or not empty
|
||||
if [ -n "${MG_NGINX_SERVER_NAME:-}" ]; then
|
||||
server_name="$MG_NGINX_SERVER_NAME"
|
||||
fi
|
||||
|
||||
echo "Copying certificate files"
|
||||
cp -v data/${server_name}.crt ${MAGISTRALA_DIR}/docker/ssl/certs/magistrala-server.crt
|
||||
cp -v data/${server_name}.key ${MAGISTRALA_DIR}/docker/ssl/certs/magistrala-server.key
|
||||
cp -v data/${MG_VAULT_PKI_INT_FILE_NAME}.key ${MAGISTRALA_DIR}/docker/ssl/certs/ca.key
|
||||
cp -v data/${MG_VAULT_PKI_INT_FILE_NAME}_bundle.crt ${MAGISTRALA_DIR}/docker/ssl/certs/ca.crt
|
||||
|
||||
exit 0
|
||||
@@ -7,18 +7,13 @@ set -euo pipefail
|
||||
scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
export MAGISTRALA_DIR=$scriptdir/../../../
|
||||
|
||||
cd $scriptdir
|
||||
|
||||
write_env() {
|
||||
sed -i "s,MG_VAULT_UNSEAL_KEY_1=.*,MG_VAULT_UNSEAL_KEY_1=$(awk -F ": " '$1 == "Unseal Key 1" {print $2}' data/secrets)," $MAGISTRALA_DIR/docker/.env
|
||||
sed -i "s,MG_VAULT_UNSEAL_KEY_2=.*,MG_VAULT_UNSEAL_KEY_2=$(awk -F ": " '$1 == "Unseal Key 2" {print $2}' data/secrets)," $MAGISTRALA_DIR/docker/.env
|
||||
sed -i "s,MG_VAULT_UNSEAL_KEY_3=.*,MG_VAULT_UNSEAL_KEY_3=$(awk -F ": " '$1 == "Unseal Key 3" {print $2}' data/secrets)," $MAGISTRALA_DIR/docker/.env
|
||||
sed -i "s,MG_VAULT_TOKEN=.*,MG_VAULT_TOKEN=$(awk -F ": " '$1 == "Initial Root Token" {print $2}' data/secrets)," $MAGISTRALA_DIR/docker/.env
|
||||
}
|
||||
vault() {
|
||||
docker exec -it magistrala-vault vault "$@"
|
||||
}
|
||||
|
||||
mkdir -p data
|
||||
|
||||
vault operator init 2>&1 | tee >(sed -r 's/\x1b\[[0-9;]*m//g' > data/secrets)
|
||||
|
||||
write_env
|
||||
Executable
+95
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/bash
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
export MAGISTRALA_DIR=$scriptdir/../../../
|
||||
|
||||
cd $scriptdir
|
||||
|
||||
SKIP_ENABLE_APP_ROLE=${1:-}
|
||||
|
||||
readDotEnv() {
|
||||
set -o allexport
|
||||
source $MAGISTRALA_DIR/docker/.env
|
||||
set +o allexport
|
||||
}
|
||||
|
||||
vault() {
|
||||
docker exec -it magistrala-vault vault "$@"
|
||||
}
|
||||
|
||||
vaultCreatePolicyFile() {
|
||||
envsubst '
|
||||
${MG_VAULT_PKI_INT_PATH}
|
||||
${MG_VAULT_PKI_INT_THINGS_CERTS_ROLE_NAME}
|
||||
' < magistrala_things_certs_issue.template.hcl > magistrala_things_certs_issue.hcl
|
||||
}
|
||||
vaultCreatePolicy() {
|
||||
echo "Creating new policy for AppRole"
|
||||
docker cp magistrala_things_certs_issue.hcl magistrala-vault:/vault/magistrala_things_certs_issue.hcl
|
||||
vault policy write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} magistrala_things_certs_issue /vault/magistrala_things_certs_issue.hcl
|
||||
}
|
||||
|
||||
vaultEnableAppRole() {
|
||||
if [ "$SKIP_ENABLE_APP_ROLE" == "skip_enable_app_role" ]; then
|
||||
echo "Skipping Enable AppRole"
|
||||
else
|
||||
echo "Enabling AppRole"
|
||||
vault auth enable -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} approle
|
||||
fi
|
||||
}
|
||||
|
||||
vaultDeleteRole() {
|
||||
echo "Deleteing old AppRole"
|
||||
vault delete -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} auth/approle/role/magistrala_things_certs_issuer
|
||||
}
|
||||
|
||||
vaultCreateRole() {
|
||||
echo "Creating new AppRole"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} auth/approle/role/magistrala_things_certs_issuer \
|
||||
token_policies=magistrala_things_certs_issue secret_id_num_uses=0 \
|
||||
secret_id_ttl=0 token_ttl=1h token_max_ttl=3h token_num_uses=0
|
||||
}
|
||||
|
||||
vaultWriteCustomRoleID(){
|
||||
echo "Writing custom role id"
|
||||
vault read -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} auth/approle/role/magistrala_things_certs_issuer/role-id
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} auth/approle/role/magistrala_things_certs_issuer/role-id role_id=${MG_VAULT_THINGS_CERTS_ISSUER_ROLEID}
|
||||
}
|
||||
|
||||
vaultWriteCustomSecret() {
|
||||
echo "Writing custom secret"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} -f auth/approle/role/magistrala_things_certs_issuer/secret-id
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} auth/approle/role/magistrala_things_certs_issuer/custom-secret-id secret_id=${MG_VAULT_THINGS_CERTS_ISSUER_SECRET} num_uses=0 ttl=0
|
||||
}
|
||||
|
||||
vaultTestRoleLogin() {
|
||||
echo "Testing custom roleid secret by logging in"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} auth/approle/login \
|
||||
role_id=${MG_VAULT_THINGS_CERTS_ISSUER_ROLEID} \
|
||||
secret_id=${MG_VAULT_THINGS_CERTS_ISSUER_SECRET}
|
||||
|
||||
}
|
||||
if ! command -v jq &> /dev/null
|
||||
then
|
||||
echo "jq command could not be found, please install it and try again."
|
||||
exit
|
||||
fi
|
||||
|
||||
readDotEnv
|
||||
|
||||
vault login -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_TOKEN}
|
||||
|
||||
vaultCreatePolicyFile
|
||||
vaultCreatePolicy
|
||||
vaultEnableAppRole
|
||||
vaultDeleteRole
|
||||
vaultCreateRole
|
||||
vaultWriteCustomRoleID
|
||||
vaultWriteCustomSecret
|
||||
vaultTestRoleLogin
|
||||
|
||||
exit 0
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/bash
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
export MAGISTRALA_DIR=$scriptdir/../../../
|
||||
|
||||
cd $scriptdir
|
||||
|
||||
vault() {
|
||||
docker exec -it magistrala-vault vault "$@"
|
||||
}
|
||||
|
||||
mkdir -p data
|
||||
|
||||
vault operator init 2>&1 | tee >(sed -r 's/\x1b\[[0-9;]*m//g' > data/secrets)
|
||||
Executable
+199
@@ -0,0 +1,199 @@
|
||||
#!/usr/bin/bash
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
export MAGISTRALA_DIR=$scriptdir/../../../
|
||||
|
||||
cd $scriptdir
|
||||
|
||||
readDotEnv() {
|
||||
set -o allexport
|
||||
source $MAGISTRALA_DIR/docker/.env
|
||||
set +o allexport
|
||||
}
|
||||
|
||||
server_name="localhost"
|
||||
|
||||
# Check if MG_NGINX_SERVER_NAME is set or not empty
|
||||
if [ -n "${MG_NGINX_SERVER_NAME:-}" ]; then
|
||||
server_name="$MG_NGINX_SERVER_NAME"
|
||||
fi
|
||||
|
||||
vault() {
|
||||
docker exec -it magistrala-vault vault "$@"
|
||||
}
|
||||
|
||||
vaultEnablePKI() {
|
||||
vault secrets enable -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} -path ${MG_VAULT_PKI_PATH} pki
|
||||
vault secrets tune -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} -max-lease-ttl=87600h ${MG_VAULT_PKI_PATH}
|
||||
}
|
||||
|
||||
vaultConfigPKIClusterPath() {
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_PATH}/config/cluster aia_path=${MG_VAULT_PKI_CLUSTER_AIA_PATH} path=${MG_VAULT_PKI_CLUSTER_PATH}
|
||||
}
|
||||
|
||||
vaultConfigPKICrl() {
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_PATH}/config/crl expiry="5m" ocsp_disable=false ocsp_expiry=0 auto_rebuild=true auto_rebuild_grace_period="2m" enable_delta=true delta_rebuild_interval="1m"
|
||||
}
|
||||
|
||||
vaultAddRoleToSecret() {
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_PATH}/roles/${MG_VAULT_PKI_ROLE_NAME} \
|
||||
allow_any_name=true \
|
||||
max_ttl="8760h" \
|
||||
default_ttl="8760h" \
|
||||
generate_lease=true
|
||||
}
|
||||
|
||||
vaultGenerateRootCACertificate() {
|
||||
echo "Generate root CA certificate"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} -format=json ${MG_VAULT_PKI_PATH}/root/generate/exported \
|
||||
common_name="\"$MG_VAULT_PKI_CA_CN\"" \
|
||||
ou="\"$MG_VAULT_PKI_CA_OU\"" \
|
||||
organization="\"$MG_VAULT_PKI_CA_O\"" \
|
||||
country="\"$MG_VAULT_PKI_CA_C\"" \
|
||||
locality="\"$MG_VAULT_PKI_CA_L\"" \
|
||||
province="\"$MG_VAULT_PKI_CA_ST\"" \
|
||||
street_address="\"$MG_VAULT_PKI_CA_ADDR\"" \
|
||||
postal_code="\"$MG_VAULT_PKI_CA_PO\"" \
|
||||
ttl=87600h | tee >(jq -r .data.certificate >data/${MG_VAULT_PKI_FILE_NAME}_ca.crt) \
|
||||
>(jq -r .data.issuing_ca >data/${MG_VAULT_PKI_FILE_NAME}_issuing_ca.crt) \
|
||||
>(jq -r .data.private_key >data/${MG_VAULT_PKI_FILE_NAME}_ca.key)
|
||||
}
|
||||
|
||||
vaultSetupRootCAIssuingURLs() {
|
||||
echo "Setup URLs for CRL and issuing"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_PATH}/config/urls \
|
||||
issuing_certificates="{{cluster_aia_path}}/v1/${MG_VAULT_PKI_PATH}/ca" \
|
||||
crl_distribution_points="{{cluster_aia_path}}/v1/${MG_VAULT_PKI_PATH}/crl" \
|
||||
ocsp_servers="{{cluster_aia_path}}/v1/${MG_VAULT_PKI_PATH}/ocsp" \
|
||||
enable_templating=true
|
||||
}
|
||||
|
||||
vaultGenerateIntermediateCAPKI() {
|
||||
echo "Generate Intermediate CA PKI"
|
||||
vault secrets enable -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} -path=${MG_VAULT_PKI_INT_PATH} pki
|
||||
vault secrets tune -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} -max-lease-ttl=43800h ${MG_VAULT_PKI_INT_PATH}
|
||||
}
|
||||
|
||||
vaultConfigIntermediatePKIClusterPath() {
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_INT_PATH}/config/cluster aia_path=${MG_VAULT_PKI_INT_CLUSTER_AIA_PATH} path=${MG_VAULT_PKI_INT_CLUSTER_PATH}
|
||||
}
|
||||
|
||||
vaultConfigIntermediatePKICrl() {
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_INT_PATH}/config/crl expiry="5m" ocsp_disable=false ocsp_expiry=0 auto_rebuild=true auto_rebuild_grace_period="2m" enable_delta=true delta_rebuild_interval="1m"
|
||||
}
|
||||
|
||||
vaultGenerateIntermediateCSR() {
|
||||
echo "Generate intermediate CSR"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} -format=json ${MG_VAULT_PKI_INT_PATH}/intermediate/generate/exported \
|
||||
common_name="\"$MG_VAULT_PKI_INT_CA_CN\"" \
|
||||
ou="\"$MG_VAULT_PKI_INT_CA_OU\""\
|
||||
organization="\"$MG_VAULT_PKI_INT_CA_O\"" \
|
||||
country="\"$MG_VAULT_PKI_INT_CA_C\"" \
|
||||
locality="\"$MG_VAULT_PKI_INT_CA_L\"" \
|
||||
province="\"$MG_VAULT_PKI_INT_CA_ST\"" \
|
||||
street_address="\"$MG_VAULT_PKI_INT_CA_ADDR\"" \
|
||||
postal_code="\"$MG_VAULT_PKI_INT_CA_PO\"" \
|
||||
| tee >(jq -r .data.csr >data/${MG_VAULT_PKI_INT_FILE_NAME}.csr) \
|
||||
>(jq -r .data.private_key >data/${MG_VAULT_PKI_INT_FILE_NAME}.key)
|
||||
}
|
||||
|
||||
vaultSignIntermediateCSR() {
|
||||
echo "Sign intermediate CSR"
|
||||
docker cp data/${MG_VAULT_PKI_INT_FILE_NAME}.csr magistrala-vault:/vault/${MG_VAULT_PKI_INT_FILE_NAME}.csr
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} -format=json ${MG_VAULT_PKI_PATH}/root/sign-intermediate \
|
||||
csr=@/vault/${MG_VAULT_PKI_INT_FILE_NAME}.csr ttl="8760h" \
|
||||
ou="\"$MG_VAULT_PKI_INT_CA_OU\""\
|
||||
organization="\"$MG_VAULT_PKI_INT_CA_O\"" \
|
||||
country="\"$MG_VAULT_PKI_INT_CA_C\"" \
|
||||
locality="\"$MG_VAULT_PKI_INT_CA_L\"" \
|
||||
province="\"$MG_VAULT_PKI_INT_CA_ST\"" \
|
||||
street_address="\"$MG_VAULT_PKI_INT_CA_ADDR\"" \
|
||||
postal_code="\"$MG_VAULT_PKI_INT_CA_PO\"" \
|
||||
| tee >(jq -r .data.certificate >data/${MG_VAULT_PKI_INT_FILE_NAME}.crt) \
|
||||
>(jq -r .data.issuing_ca >data/${MG_VAULT_PKI_INT_FILE_NAME}_issuing_ca.crt)
|
||||
}
|
||||
|
||||
vaultInjectIntermediateCertificate() {
|
||||
echo "Inject Intermediate Certificate"
|
||||
docker cp data/${MG_VAULT_PKI_INT_FILE_NAME}.crt magistrala-vault:/vault/${MG_VAULT_PKI_INT_FILE_NAME}.crt
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_INT_PATH}/intermediate/set-signed certificate=@/vault/${MG_VAULT_PKI_INT_FILE_NAME}.crt
|
||||
}
|
||||
|
||||
vaultGenerateIntermediateCertificateBundle() {
|
||||
echo "Generate intermediate certificate bundle"
|
||||
cat data/${MG_VAULT_PKI_INT_FILE_NAME}.crt data/${MG_VAULT_PKI_FILE_NAME}_ca.crt \
|
||||
> data/${MG_VAULT_PKI_INT_FILE_NAME}_bundle.crt
|
||||
}
|
||||
|
||||
vaultSetupIntermediateIssuingURLs() {
|
||||
echo "Setup URLs for CRL and issuing"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_INT_PATH}/config/urls \
|
||||
issuing_certificates="{{cluster_aia_path}}/v1/${MG_VAULT_PKI_INT_PATH}/ca" \
|
||||
crl_distribution_points="{{cluster_aia_path}}/v1/${MG_VAULT_PKI_INT_PATH}/crl" \
|
||||
ocsp_servers="{{cluster_aia_path}}/v1/${MG_VAULT_PKI_INT_PATH}/ocsp" \
|
||||
enable_templating=true
|
||||
}
|
||||
|
||||
vaultSetupServerCertsRole() {
|
||||
echo "Setup Server Certs role"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_INT_PATH}/roles/${MG_VAULT_PKI_INT_SERVER_CERTS_ROLE_NAME} \
|
||||
allow_subdomains=true \
|
||||
max_ttl="4320h"
|
||||
}
|
||||
|
||||
vaultGenerateServerCertificate() {
|
||||
echo "Generate server certificate"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} -format=json ${MG_VAULT_PKI_INT_PATH}/issue/${MG_VAULT_PKI_INT_SERVER_CERTS_ROLE_NAME} \
|
||||
common_name="$server_name" ttl="4320h" \
|
||||
| tee >(jq -r .data.certificate >data/${server_name}.crt) \
|
||||
>(jq -r .data.private_key >data/${server_name}.key)
|
||||
}
|
||||
|
||||
vaultSetupThingCertsRole() {
|
||||
echo "Setup Thing Certs role"
|
||||
vault write -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_PKI_INT_PATH}/roles/${MG_VAULT_PKI_INT_THINGS_CERTS_ROLE_NAME} \
|
||||
allow_subdomains=true \
|
||||
allow_any_name=true \
|
||||
max_ttl="2160h"
|
||||
}
|
||||
|
||||
vaultCleanupFiles() {
|
||||
docker exec magistrala-vault sh -c 'rm -rf /vault/*.{crt,csr}'
|
||||
}
|
||||
|
||||
if ! command -v jq &> /dev/null
|
||||
then
|
||||
echo "jq command could not be found, please install it and try again."
|
||||
exit
|
||||
fi
|
||||
|
||||
readDotEnv
|
||||
|
||||
mkdir -p data
|
||||
|
||||
vault login -namespace=${MG_VAULT_NAMESPACE} -address=${MG_VAULT_ADDR} ${MG_VAULT_TOKEN}
|
||||
|
||||
vaultEnablePKI
|
||||
vaultConfigPKIClusterPath
|
||||
vaultConfigPKICrl
|
||||
vaultAddRoleToSecret
|
||||
vaultGenerateRootCACertificate
|
||||
vaultSetupRootCAIssuingURLs
|
||||
vaultGenerateIntermediateCAPKI
|
||||
vaultConfigIntermediatePKIClusterPath
|
||||
vaultConfigIntermediatePKICrl
|
||||
vaultGenerateIntermediateCSR
|
||||
vaultSignIntermediateCSR
|
||||
vaultInjectIntermediateCertificate
|
||||
vaultGenerateIntermediateCertificateBundle
|
||||
vaultSetupIntermediateIssuingURLs
|
||||
vaultSetupServerCertsRole
|
||||
vaultGenerateServerCertificate
|
||||
vaultSetupThingCertsRole
|
||||
vaultCleanupFiles
|
||||
|
||||
exit 0
|
||||
@@ -234,10 +234,18 @@ services:
|
||||
- ./nginx/entrypoint.sh:/docker-entrypoint.d/entrypoint.sh
|
||||
- ./nginx/snippets:/etc/nginx/snippets
|
||||
- ./ssl/authorization.js:/etc/nginx/authorization.js
|
||||
- ./ssl/certs/magistrala-server.crt:/etc/ssl/certs/magistrala-server.crt
|
||||
- ./ssl/certs/ca.crt:/etc/ssl/certs/ca.crt
|
||||
- ./ssl/certs/magistrala-server.key:/etc/ssl/private/magistrala-server.key
|
||||
- ./ssl/dhparam.pem:/etc/ssl/certs/dhparam.pem
|
||||
- type: bind
|
||||
source: ${MG_NGINX_SERVER_CERT:-./ssl/certs/magistrala-server.crt}
|
||||
target: /etc/ssl/certs/magistrala-server.crt
|
||||
- type: bind
|
||||
source: ${MG_NGINX_SERVER_KEY:-./ssl/certs/magistrala-server.key}
|
||||
target: /etc/ssl/private/magistrala-server.key
|
||||
- type: bind
|
||||
source: ${MG_NGINX_SERVER_CLIENT_CA:-./ssl/certs/ca.crt}
|
||||
target: /etc/ssl/certs/ca.crt
|
||||
- type: bind
|
||||
source: ${MG_NGINX_SERVER_DHPARAM:-./ssl/dhparam.pem}
|
||||
target: /etc/ssl/certs/dhparam.pem
|
||||
ports:
|
||||
- ${MG_NGINX_HTTP_PORT}:${MG_NGINX_HTTP_PORT}
|
||||
- ${MG_NGINX_SSL_PORT}:${MG_NGINX_SSL_PORT}
|
||||
@@ -716,7 +724,7 @@ services:
|
||||
MG_UI_DB_SSL_MODE: ${MG_UI_DB_SSL_MODE}
|
||||
MG_UI_DB_SSL_CERT: ${MG_UI_DB_SSL_CERT}
|
||||
MG_UI_DB_SSL_KEY: ${MG_UI_DB_SSL_KEY}
|
||||
MG_UI_DB_SSL_ROOT_CERT: ${MG_UI_DB_SSL_ROOT_CERT}
|
||||
MG_UI_DB_SSL_ROOT_CERT: ${MG_UI_DB_SSL_ROOT_CERT}
|
||||
ports:
|
||||
- ${MG_UI_PORT}:${MG_UI_PORT}
|
||||
networks:
|
||||
|
||||
@@ -12,6 +12,7 @@ else
|
||||
fi
|
||||
|
||||
envsubst '
|
||||
${MG_NGINX_SERVER_NAME}
|
||||
${MG_AUTH_HTTP_PORT}
|
||||
${MG_USERS_HTTP_PORT}
|
||||
${MG_THINGS_HTTP_PORT}
|
||||
|
||||
@@ -39,6 +39,14 @@ http {
|
||||
listen 443 ssl http2 default_server;
|
||||
listen [::]:443 ssl http2 default_server;
|
||||
|
||||
set $dynamic_server_name "$MG_NGINX_SERVER_NAME";
|
||||
|
||||
if ($dynamic_server_name = '') {
|
||||
set $dynamic_server_name "localhost";
|
||||
}
|
||||
|
||||
server_name $dynamic_server_name;
|
||||
|
||||
include snippets/ssl.conf;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
|
||||
@@ -48,8 +56,6 @@ http {
|
||||
add_header Access-Control-Allow-Methods '*';
|
||||
add_header Access-Control-Allow-Headers '*';
|
||||
|
||||
server_name localhost;
|
||||
|
||||
location ~ ^/(channels)/(.+)/(things)/(.+) {
|
||||
include snippets/proxy-headers.conf;
|
||||
add_header Access-Control-Expose-Headers Location;
|
||||
|
||||
@@ -45,6 +45,15 @@ http {
|
||||
listen [::]:80 default_server;
|
||||
listen 443 ssl http2 default_server;
|
||||
listen [::]:443 ssl http2 default_server;
|
||||
|
||||
set $dynamic_server_name "$MG_NGINX_SERVER_NAME";
|
||||
|
||||
if ($dynamic_server_name = '') {
|
||||
set $dynamic_server_name "localhost";
|
||||
}
|
||||
|
||||
server_name $dynamic_server_name;
|
||||
|
||||
ssl_verify_client optional;
|
||||
include snippets/ssl.conf;
|
||||
include snippets/ssl-client.conf;
|
||||
@@ -56,8 +65,6 @@ http {
|
||||
add_header Access-Control-Allow-Methods '*';
|
||||
add_header Access-Control-Allow-Headers '*';
|
||||
|
||||
server_name localhost;
|
||||
|
||||
# Proxy pass to users service
|
||||
location ~ ^/(users|groups|password|policies|authorize) {
|
||||
include snippets/proxy-headers.conf;
|
||||
@@ -69,7 +76,7 @@ http {
|
||||
include snippets/proxy-headers.conf;
|
||||
add_header Access-Control-Expose-Headers Location;
|
||||
proxy_pass http://users:${MG_USERS_HTTP_PORT}/policies;
|
||||
}
|
||||
}
|
||||
|
||||
# Proxy pass to things service
|
||||
location ~ ^/(things|channels|connect|disconnect|identify) {
|
||||
@@ -77,7 +84,7 @@ http {
|
||||
add_header Access-Control-Expose-Headers Location;
|
||||
proxy_pass http://things:${MG_THINGS_HTTP_PORT};
|
||||
}
|
||||
|
||||
|
||||
location ^~ /things/policies {
|
||||
include snippets/proxy-headers.conf;
|
||||
add_header Access-Control-Expose-Headers Location;
|
||||
@@ -90,7 +97,7 @@ http {
|
||||
add_header Access-Control-Expose-Headers Location;
|
||||
proxy_pass http://invitations:${MG_INVITATIONS_HTTP_PORT};
|
||||
}
|
||||
|
||||
|
||||
location /health {
|
||||
include snippets/proxy-headers.conf;
|
||||
proxy_pass http://things:${MG_THINGS_HTTP_PORT};
|
||||
@@ -100,7 +107,7 @@ http {
|
||||
include snippets/proxy-headers.conf;
|
||||
proxy_pass http://things:${MG_THINGS_HTTP_PORT};
|
||||
}
|
||||
|
||||
|
||||
# Proxy pass to magistrala-http-adapter
|
||||
location /http/ {
|
||||
include snippets/verify-ssl-client.conf;
|
||||
|
||||
@@ -25,7 +25,7 @@ require (
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/gopcua/opcua v0.1.6
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/hashicorp/vault/api v1.10.0
|
||||
github.com/hashicorp/vault/api v1.12.0
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.13.0
|
||||
github.com/ivanpirog/coloredcobra v1.0.1
|
||||
@@ -54,8 +54,8 @@ require (
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0
|
||||
go.opentelemetry.io/otel/sdk v1.22.0
|
||||
go.opentelemetry.io/otel/trace v1.22.0
|
||||
golang.org/x/crypto v0.18.0
|
||||
golang.org/x/net v0.20.0
|
||||
golang.org/x/crypto v0.19.0
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/sync v0.6.0
|
||||
gonum.org/v1/gonum v0.14.0
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac
|
||||
@@ -110,6 +110,7 @@ require (
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.6 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/vault/api/auth/approle v0.6.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf // indirect
|
||||
@@ -174,7 +175,7 @@ require (
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
|
||||
@@ -26,6 +26,7 @@ github.com/absmach/senml v1.0.5 h1:zNPRYpGr2Wsb8brAusz8DIfFqemy1a2dNbmMnegY3GE=
|
||||
github.com/absmach/senml v1.0.5/go.mod h1:NDEjk3O4V4YYu9Bs2/+t/AZ/F+0wu05ikgecp+/FsSU=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/authzed/authzed-go v0.10.1 h1:0aX2Ox9PPPknID92kLs/FnmhCmfl6Ni16v3ZTLsds5M=
|
||||
github.com/authzed/authzed-go v0.10.1/go.mod h1:ZsaFPCiMjwT0jLW0gCyYzh3elHqhKDDGGRySyykXwqc=
|
||||
github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 h1:bQeIwWWRI9bl93poTqpix4sYHi+gnXUPK7N6bMtXzBE=
|
||||
@@ -33,6 +34,7 @@ github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403/go.mod h1:s3qC7V7
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||
github.com/bitly/go-hostpool v0.1.0 h1:XKmsF6k5el6xHG3WPJ8U0Ku/ye7njX7W81Ng7O2ioR0=
|
||||
github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw=
|
||||
@@ -41,7 +43,9 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4Yn
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/caarlos0/env/v10 v10.0.0 h1:yIHUBZGsyqCnpTkbjk8asUlx6RFhhEs+h7TOBdgdzXA=
|
||||
github.com/caarlos0/env/v10 v10.0.0/go.mod h1:ZfulV76NvVPw3tm591U4SwL3Xx9ldzBP9aGxzeN7G18=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
|
||||
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
@@ -95,6 +99,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
@@ -179,6 +184,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
@@ -203,27 +209,38 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMW
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
|
||||
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 h1:iBt4Ew4XEGLfh6/bPk4rSYmuZJGizr6/x/AEizP0CQc=
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8/go.mod h1:aiJI+PIApBRQG7FZTEBx5GiiX+HbOHilUdNxUZi4eV0=
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U=
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||
github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I=
|
||||
github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/vault/api v1.10.0 h1:/US7sIjWN6Imp4o/Rj1Ce2Nr5bki/AXi9vAW3p2tOJQ=
|
||||
github.com/hashicorp/vault/api v1.10.0/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8=
|
||||
github.com/hashicorp/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
|
||||
github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
|
||||
github.com/hashicorp/vault/api/auth/approle v0.6.0 h1:ELfFFQlTM/e97WJKu1HvNFa7lQ3tlTwwzrR1NJE1V7Y=
|
||||
github.com/hashicorp/vault/api/auth/approle v0.6.0/go.mod h1:CCoIl1xBC3lAWpd1HV+0ovk76Z8b8Mdepyk21h3pGk0=
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f h1:7LYC+Yfkj3CTRcShK0KOL/w6iTiKyqqBA9a41Wnggw8=
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
@@ -339,13 +356,18 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
@@ -355,8 +377,11 @@ github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A
|
||||
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
|
||||
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
@@ -424,6 +449,7 @@ github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90/go.mod h1:Z7oKFLSG
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY=
|
||||
github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
@@ -447,6 +473,7 @@ github.com/rubenv/sql-migrate v1.6.1 h1:bo6/sjsan9HaXAsNxYP/jCEDUGibHp8JmOBw7NTG
|
||||
github.com/rubenv/sql-migrate v1.6.1/go.mod h1:tPzespupJS0jacLfhbwto/UjSX+8h2FdWB7ar+QlHa0=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
@@ -589,8 +616,12 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
@@ -630,8 +661,11 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
@@ -646,6 +680,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -657,6 +692,7 @@ golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -678,8 +714,12 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -687,6 +727,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -697,8 +739,10 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
|
||||
Reference in New Issue
Block a user