mirror of https://github.com/docusealco/docuseal
Merge pull request #9 from CareerPlug/staging-deployment-infra
Staging infrastructure supportpull/544/head
commit
6228b8a037
@ -0,0 +1,6 @@
|
|||||||
|
DB_HOST=host.docker.internal
|
||||||
|
DB_PASSWORD=postgres
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_USERNAME=postgres
|
||||||
|
REDIS_URL=redis://host.docker.internal:6379/7
|
||||||
|
PORT=3000
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
DB_HOST=
|
||||||
|
DB_POOL=25
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_SSLCERT=/config/rds-combined-ca-bundle.pem
|
||||||
|
DB_SSLMODE=verify-full
|
||||||
|
REDIS_URL=
|
||||||
|
PORT=3000
|
||||||
|
S3_ATTACHMENTS_BUCKET=
|
||||||
|
ACTIVE_STORAGE_PUBLIC=true
|
||||||
@ -0,0 +1,211 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
echo "=== CP Docuseal Staging Startup ==="
|
||||||
|
|
||||||
|
# Enable jemalloc for reduced memory usage and latency.
|
||||||
|
if [ -z "${LD_PRELOAD+x}" ]; then
|
||||||
|
LD_PRELOAD=$(find /usr/lib -name libjemalloc.so.2 -print -quit)
|
||||||
|
export LD_PRELOAD
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_aws_setup() {
|
||||||
|
if [ -z "$AWS_REGION" ]; then
|
||||||
|
echo "ERROR: AWS_REGION environment variable is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v aws &> /dev/null; then
|
||||||
|
echo "ERROR: AWS CLI is not installed. Please install it to proceed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to fetch secrets from AWS Secrets Manager
|
||||||
|
fetch_db_credentials() {
|
||||||
|
echo "Fetching database credentials from AWS Secrets Manager..."
|
||||||
|
|
||||||
|
if [ -z "$DB_SECRETS_NAME" ]; then
|
||||||
|
echo "ERROR: DB_SECRETS_NAME environment variable is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fetch the secret
|
||||||
|
echo "Retrieving secret: $DB_SECRETS_NAME"
|
||||||
|
SECRET_JSON=$(aws secretsmanager get-secret-value \
|
||||||
|
--region "$AWS_REGION" \
|
||||||
|
--secret-id "$DB_SECRETS_NAME" \
|
||||||
|
--query SecretString \
|
||||||
|
--output text)
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to retrieve secrets from AWS Secrets Manager"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse JSON and export environment variables
|
||||||
|
export DB_USERNAME=$(echo "$SECRET_JSON" | jq -r '.username')
|
||||||
|
export DB_PASSWORD=$(echo "$SECRET_JSON" | jq -r '.password')
|
||||||
|
|
||||||
|
# Validate that we got the credentials
|
||||||
|
if [ "$DB_USERNAME" = "null" ] || [ "$DB_PASSWORD" = "null" ] || [ -z "$DB_USERNAME" ] || [ -z "$DB_PASSWORD" ]; then
|
||||||
|
echo "ERROR: Failed to parse database credentials from secrets"
|
||||||
|
echo "Expected JSON format: {\"username\": \"...\", \"password\": \"...\"}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Write credentials to .env.staging file
|
||||||
|
echo "Writing database credentials to .env.staging..."
|
||||||
|
|
||||||
|
# Remove existing DB_USERNAME and DB_PASSWORD lines if they exist
|
||||||
|
if [ -f "./.env.staging" ]; then
|
||||||
|
echo "Removing existing DB_USERNAME and DB_PASSWORD from .env.staging"
|
||||||
|
grep -v "^DB_USERNAME=" ./.env.staging > ./.env.staging.tmp || true
|
||||||
|
grep -v "^DB_PASSWORD=" ./.env.staging.tmp > ./.env.staging || true
|
||||||
|
rm -f ./.env.staging.tmp
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Append the new credentials
|
||||||
|
echo "DB_USERNAME=$DB_USERNAME" >> ./.env.staging
|
||||||
|
echo "DB_PASSWORD=$DB_PASSWORD" >> ./.env.staging
|
||||||
|
|
||||||
|
echo "✓ Database credentials successfully retrieved and written to .env.staging"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to fetch encryption key from AWS Secrets Manager and write to config/master.key
|
||||||
|
fetch_encryption_key() {
|
||||||
|
echo "Fetching encryption key from AWS Secrets Manager..."
|
||||||
|
|
||||||
|
ENCRYPTION_SECRET_NAME="cpdocuseal/encryption_key"
|
||||||
|
if [ -z "$AWS_REGION" ]; then
|
||||||
|
echo "ERROR: AWS_REGION environment variable is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fetch the secret value (assume it's a plain string, not JSON)
|
||||||
|
ENCRYPTION_KEY=$(aws secretsmanager get-secret-value \
|
||||||
|
--region "$AWS_REGION" \
|
||||||
|
--secret-id "$ENCRYPTION_SECRET_NAME" \
|
||||||
|
--query SecretString \
|
||||||
|
--output text)
|
||||||
|
|
||||||
|
if [ $? -ne 0 ] || [ -z "$ENCRYPTION_KEY" ] || [ "$ENCRYPTION_KEY" = "null" ]; then
|
||||||
|
echo "ERROR: Failed to retrieve encryption key from AWS Secrets Manager"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Write the key to config/master.key
|
||||||
|
echo -n "$ENCRYPTION_KEY" > config/master.key
|
||||||
|
chmod 600 config/master.key
|
||||||
|
echo "✓ Encryption key written to config/master.key"
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch_env_variables() {
|
||||||
|
echo "Fetching environment variables from AWS Secrets Manager..."
|
||||||
|
|
||||||
|
if [ -z "$CP_VARIABLES_NAME" ]; then
|
||||||
|
echo "ERROR: CP_VARIABLES_NAME environment variable is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fetch the secret
|
||||||
|
echo "Retrieving secret: $CP_VARIABLES_NAME"
|
||||||
|
SECRET_JSON=$(aws secretsmanager get-secret-value \
|
||||||
|
--region "$AWS_REGION" \
|
||||||
|
--secret-id "$CP_VARIABLES_NAME" \
|
||||||
|
--query SecretString \
|
||||||
|
--output text)
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to retrieve secrets from AWS Secrets Manager"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DB_HOST=$(echo "$SECRET_JSON" | jq -r '.host')
|
||||||
|
export REDIS_URL=$(echo "$SECRET_JSON" | jq -r '.redis_url')
|
||||||
|
export S3_ATTACHMENTS_BUCKET=$(echo "$SECRET_JSON" | jq -r '.s3_attachments_bucket')
|
||||||
|
|
||||||
|
# Validate that we got the values
|
||||||
|
if [ "$DB_HOST" = "null" ] || [ "$REDIS_URL" = "null" ] || [ "$S3_ATTACHMENTS_BUCKET" = "null" ] || [ -z "$DB_HOST" ] || [ -z "$REDIS_URL" ] || [ -z "$S3_ATTACHMENTS_BUCKET" ]; then
|
||||||
|
echo "ERROR: Failed to parse variables from secrets"
|
||||||
|
echo "Expected JSON format: {\"key\": \"...\", ...}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Write variables to .env.staging file
|
||||||
|
echo "Writing environment variables to .env.staging..."
|
||||||
|
|
||||||
|
# Remove existing DB_HOST, REDIS_URL, and S3_ATTACHMENTS_BUCKET lines if they exist
|
||||||
|
if [ -f "./.env.staging" ]; then
|
||||||
|
echo "Removing existing variables from .env.staging"
|
||||||
|
grep -v "^DB_HOST=" ./.env.staging > ./.env.staging.tmp || true
|
||||||
|
grep -v "^REDIS_URL=" ./.env.staging.tmp > ./.env.staging || true
|
||||||
|
grep -v "^S3_ATTACHMENTS_BUCKET=" ./.env.staging.tmp > ./.env.staging || true
|
||||||
|
rm -f ./.env.staging.tmp
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Append the new credentials
|
||||||
|
echo "DB_HOST=$DB_HOST" >> ./.env.staging
|
||||||
|
echo "REDIS_URL=$REDIS_URL" >> ./.env.staging
|
||||||
|
echo "S3_ATTACHMENTS_BUCKET=$S3_ATTACHMENTS_BUCKET" >> ./.env.staging
|
||||||
|
|
||||||
|
echo "✓ Environment variables successfully retrieved and written to .env.staging"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to setup database
|
||||||
|
setup_database() {
|
||||||
|
echo "Running database migrations..."
|
||||||
|
./bin/rails db:migrate
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✓ Database migrations completed successfully"
|
||||||
|
else
|
||||||
|
echo "ERROR: Database migrations failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
set_environment() {
|
||||||
|
if [ -f "./.env.staging" ]; then
|
||||||
|
echo "Setting environment variables from .env.staging"
|
||||||
|
set -a
|
||||||
|
. ./.env.staging
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
main() {
|
||||||
|
cd ../../app/
|
||||||
|
|
||||||
|
set_environment
|
||||||
|
|
||||||
|
check_aws_setup
|
||||||
|
|
||||||
|
echo "Starting CP Docuseal in staging mode..."
|
||||||
|
echo "Rails Environment: ${RAILS_ENV:-staging}"
|
||||||
|
|
||||||
|
# Fetch database credentials from Secrets Manager
|
||||||
|
fetch_db_credentials
|
||||||
|
|
||||||
|
# Fetch encryption key and write to config/master.key
|
||||||
|
fetch_encryption_key
|
||||||
|
|
||||||
|
# Fetch other environment variables from Secrets Manager
|
||||||
|
fetch_env_variables
|
||||||
|
|
||||||
|
# Load updated environment variables
|
||||||
|
set_environment
|
||||||
|
|
||||||
|
# Setup and migrate database
|
||||||
|
setup_database
|
||||||
|
|
||||||
|
echo "=== Startup Complete - Starting Rails Server ==="
|
||||||
|
echo "Database Host: ${DB_HOST:-not set}"
|
||||||
|
echo "Database Port: ${DB_PORT:-not set}"
|
||||||
|
|
||||||
|
# Start the Rails server
|
||||||
|
exec ./bin/rails server -b 0.0.0.0 -p "${PORT:-3000}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execute main function with all arguments
|
||||||
|
main "$@"
|
||||||
@ -0,0 +1,164 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'active_support/core_ext/integer/time'
|
||||||
|
require 'active_support/core_ext/string'
|
||||||
|
|
||||||
|
Rails.backtrace_cleaner.remove_silencers!
|
||||||
|
|
||||||
|
Rails.application.configure do
|
||||||
|
# Settings specified here will take precedence over those in config/application.rb.
|
||||||
|
|
||||||
|
# Code is not reloaded between requests.
|
||||||
|
config.enable_reloading = false
|
||||||
|
|
||||||
|
config.public_file_server.headers = {
|
||||||
|
'cache-control' => 'public, s-maxage=31536000, max-age=15552000',
|
||||||
|
'Expires' => 1.year.from_now.to_fs(:rfc822)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Eager load code on boot. This eager loads most of Rails and
|
||||||
|
# your application in memory, allowing both threaded web servers
|
||||||
|
# and those relying on copy on write to perform better.
|
||||||
|
# Rake tasks automatically ignore this option for performance.
|
||||||
|
config.eager_load = true
|
||||||
|
|
||||||
|
# Full error reports are disabled and caching is turned on.
|
||||||
|
config.consider_all_requests_local = false
|
||||||
|
config.action_controller.perform_caching = true
|
||||||
|
|
||||||
|
config.active_job.queue_adapter = :sidekiq
|
||||||
|
|
||||||
|
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
|
||||||
|
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
|
||||||
|
# config.require_master_key = true
|
||||||
|
|
||||||
|
# Disable serving static files from the `/public` folder by default since
|
||||||
|
# Apache or NGINX already handles this.
|
||||||
|
config.public_file_server.enabled = true
|
||||||
|
|
||||||
|
# Store uploaded files on the local file system (see config/storage.yml for options).
|
||||||
|
config.active_storage.service = :aws_s3
|
||||||
|
|
||||||
|
config.active_storage.resolve_model_to_route = :rails_storage_proxy if ENV['ACTIVE_STORAGE_PUBLIC'] != 'true'
|
||||||
|
config.active_storage.service_urls_expire_in = ENV.fetch('PRESIGNED_URLS_EXPIRE_MINUTES', '240').to_i.minutes
|
||||||
|
|
||||||
|
# Mount Action Cable outside main process or domain.
|
||||||
|
# config.action_cable.mount_path = nil
|
||||||
|
# config.action_cable.url = "wss://example.com/cable"
|
||||||
|
# config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]
|
||||||
|
|
||||||
|
# Assume all access to the app is happening through a SSL-terminating reverse proxy.
|
||||||
|
config.assume_ssl = ENV['FORCE_SSL'].present? && ENV['FORCE_SSL'] != 'false'
|
||||||
|
|
||||||
|
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
||||||
|
config.force_ssl = ENV['FORCE_SSL'].present? && ENV['FORCE_SSL'] != 'false'
|
||||||
|
|
||||||
|
# Include generic and useful information about system operation, but avoid logging too much
|
||||||
|
# information to avoid inadvertent exposure of personally identifiable information (PII).
|
||||||
|
config.log_level = :info
|
||||||
|
|
||||||
|
# Prepend all log lines with the following tags.
|
||||||
|
config.log_tags = [:request_id]
|
||||||
|
|
||||||
|
config.cache_store = :memory_store
|
||||||
|
|
||||||
|
config.action_mailer.perform_caching = false
|
||||||
|
|
||||||
|
# Ignore bad email addresses and do not raise email delivery errors.
|
||||||
|
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||||
|
config.action_mailer.raise_delivery_errors = false
|
||||||
|
|
||||||
|
if ENV['SMTP_ADDRESS']
|
||||||
|
config.action_mailer.delivery_method = :smtp
|
||||||
|
config.action_mailer.smtp_settings = {
|
||||||
|
address: ENV.fetch('SMTP_ADDRESS', nil),
|
||||||
|
port: ENV.fetch('SMTP_PORT', 587),
|
||||||
|
domain: ENV.fetch('SMTP_DOMAIN', nil),
|
||||||
|
user_name: ENV.fetch('SMTP_USERNAME', nil),
|
||||||
|
password: ENV.fetch('SMTP_PASSWORD', nil),
|
||||||
|
authentication: ENV.fetch('SMTP_PASSWORD', nil).present? ? ENV.fetch('SMTP_AUTHENTICATION', 'plain') : nil,
|
||||||
|
enable_starttls_auto: ENV['SMTP_ENABLE_STARTTLS_AUTO'] != 'false'
|
||||||
|
}.compact
|
||||||
|
end
|
||||||
|
|
||||||
|
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||||
|
# the I18n.default_locale when a translation cannot be found).
|
||||||
|
config.i18n.fallbacks = true
|
||||||
|
|
||||||
|
# Don't log any deprecations.
|
||||||
|
config.active_support.report_deprecations = false
|
||||||
|
|
||||||
|
# Use default logging formatter so that PID and timestamp are not suppressed.
|
||||||
|
config.log_formatter = Logger::Formatter.new
|
||||||
|
|
||||||
|
# Use a different logger for distributed setups.
|
||||||
|
# require "syslog/logger"
|
||||||
|
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")
|
||||||
|
|
||||||
|
logger = ActiveSupport::Logger.new($stdout)
|
||||||
|
logger.formatter = config.log_formatter
|
||||||
|
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
||||||
|
|
||||||
|
encryption_secret = ENV['ENCRYPTION_SECRET'].presence || Digest::SHA256.hexdigest(ENV['SECRET_KEY_BASE'].to_s)
|
||||||
|
|
||||||
|
config.active_record.encryption = {
|
||||||
|
primary_key: encryption_secret.first(32),
|
||||||
|
deterministic_key: encryption_secret.last(32),
|
||||||
|
key_derivation_salt: Digest::SHA256.hexdigest(encryption_secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveRecord::Encryption.configure(**config.active_record.encryption)
|
||||||
|
|
||||||
|
# Do not dump schema after migrations.
|
||||||
|
config.active_record.dump_schema_after_migration = false
|
||||||
|
|
||||||
|
config.lograge.enabled = true
|
||||||
|
config.lograge.base_controller_class = ['ActionController::API', 'ActionController::Base']
|
||||||
|
|
||||||
|
config.lograge.formatter = ->(data) { data.except(:path, :location).to_json }
|
||||||
|
|
||||||
|
config.lograge.custom_payload do |controller|
|
||||||
|
params =
|
||||||
|
begin
|
||||||
|
controller.request.try(:params) || {}
|
||||||
|
rescue StandardError
|
||||||
|
{}
|
||||||
|
end
|
||||||
|
|
||||||
|
resource = controller.instance_variable_get(:@submitter) ||
|
||||||
|
controller.instance_variable_get(:@submission) ||
|
||||||
|
controller.instance_variable_get(:@template) ||
|
||||||
|
controller.instance_variable_get(:@record)
|
||||||
|
|
||||||
|
current_user = controller.instance_variable_get(:@current_user)
|
||||||
|
|
||||||
|
{
|
||||||
|
host: controller.request.host,
|
||||||
|
fwd: controller.request.remote_ip,
|
||||||
|
params: {
|
||||||
|
id: params[:id],
|
||||||
|
template_id: params[:template_id],
|
||||||
|
submission_id: params[:submission_id],
|
||||||
|
submitter_id: params[:submitter_id],
|
||||||
|
sig: (params[:signed_uuid] || params[:signed_id]).to_s.split('--').first,
|
||||||
|
slug: (params[:slug] ||
|
||||||
|
params[:submitter_slug] ||
|
||||||
|
params[:submission_slug] ||
|
||||||
|
params[:submit_form_slug] ||
|
||||||
|
params[:template_slug]).to_s.first(5)
|
||||||
|
}.compact_blank,
|
||||||
|
uid: current_user.try(:id),
|
||||||
|
aid: current_user.try(:account_id),
|
||||||
|
rid: resource.try(:id),
|
||||||
|
raid: resource.try(:account_id)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
config.host_authorization = { exclude: ->(request) { request.path == '/up' } }
|
||||||
|
[
|
||||||
|
/.*\.careerplug\.org\Z/,
|
||||||
|
/.*\.careerplug\.com\Z/,
|
||||||
|
/.*\.cpstaging\d\.click\Z/,
|
||||||
|
/.*\.cpstaging\d+\.name\Z/
|
||||||
|
].each { |hrexp| config.hosts << hrexp }
|
||||||
|
end
|
||||||
@ -0,0 +1,124 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEBjCCAu6gAwIBAgIJAMc0ZzaSUK51MA0GCSqGSIb3DQEBCwUAMIGPMQswCQYD
|
||||||
|
VQQGEwJVUzEQMA4GA1UEBwwHU2VhdHRsZTETMBEGA1UECAwKV2FzaGluZ3RvbjEi
|
||||||
|
MCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEGA1UECwwKQW1h
|
||||||
|
em9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJEUyBSb290IDIwMTkgQ0EwHhcNMTkw
|
||||||
|
ODIyMTcwODUwWhcNMjQwODIyMTcwODUwWjCBjzELMAkGA1UEBhMCVVMxEDAOBgNV
|
||||||
|
BAcMB1NlYXR0bGUxEzARBgNVBAgMCldhc2hpbmd0b24xIjAgBgNVBAoMGUFtYXpv
|
||||||
|
biBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxIDAeBgNV
|
||||||
|
BAMMF0FtYXpvbiBSRFMgUm9vdCAyMDE5IENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||||
|
AQ8AMIIBCgKCAQEArXnF/E6/Qh+ku3hQTSKPMhQQlCpoWvnIthzX6MK3p5a0eXKZ
|
||||||
|
oWIjYcNNG6UwJjp4fUXl6glp53Jobn+tWNX88dNH2n8DVbppSwScVE2LpuL+94vY
|
||||||
|
0EYE/XxN7svKea8YvlrqkUBKyxLxTjh+U/KrGOaHxz9v0l6ZNlDbuaZw3qIWdD/I
|
||||||
|
6aNbGeRUVtpM6P+bWIoxVl/caQylQS6CEYUk+CpVyJSkopwJlzXT07tMoDL5WgX9
|
||||||
|
O08KVgDNz9qP/IGtAcRduRcNioH3E9v981QO1zt/Gpb2f8NqAjUUCUZzOnij6mx9
|
||||||
|
McZ+9cWX88CRzR0vQODWuZscgI08NvM69Fn2SQIDAQABo2MwYTAOBgNVHQ8BAf8E
|
||||||
|
BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUc19g2LzLA5j0Kxc0LjZa
|
||||||
|
pmD/vB8wHwYDVR0jBBgwFoAUc19g2LzLA5j0Kxc0LjZapmD/vB8wDQYJKoZIhvcN
|
||||||
|
AQELBQADggEBAHAG7WTmyjzPRIM85rVj+fWHsLIvqpw6DObIjMWokpliCeMINZFV
|
||||||
|
ynfgBKsf1ExwbvJNzYFXW6dihnguDG9VMPpi2up/ctQTN8tm9nDKOy08uNZoofMc
|
||||||
|
NUZxKCEkVKZv+IL4oHoeayt8egtv3ujJM6V14AstMQ6SwvwvA93EP/Ug2e4WAXHu
|
||||||
|
cbI1NAbUgVDqp+DRdfvZkgYKryjTWd/0+1fS8X1bBZVWzl7eirNVnHbSH2ZDpNuY
|
||||||
|
0SBd8dj5F6ld3t58ydZbrTHze7JJOd8ijySAp4/kiu9UfZWuTPABzDa/DSdz9Dk/
|
||||||
|
zPW4CXXvhLmE02TA9/HeCw3KEHIwicNuEfw=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEBzCCAu+gAwIBAgICJVUwDQYJKoZIhvcNAQELBQAwgY8xCzAJBgNVBAYTAlVT
|
||||||
|
MRAwDgYDVQQHDAdTZWF0dGxlMRMwEQYDVQQIDApXYXNoaW5ndG9uMSIwIAYDVQQK
|
||||||
|
DBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJbmMuMRMwEQYDVQQLDApBbWF6b24gUkRT
|
||||||
|
MSAwHgYDVQQDDBdBbWF6b24gUkRTIFJvb3QgMjAxOSBDQTAeFw0xOTA5MTkxODE2
|
||||||
|
NTNaFw0yNDA4MjIxNzA4NTBaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2Fz
|
||||||
|
aGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBT
|
||||||
|
ZXJ2aWNlcywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzElMCMGA1UEAwwcQW1h
|
||||||
|
em9uIFJEUyB1cy1lYXN0LTEgMjAxOSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAM3i/k2u6cqbMdcISGRvh+m+L0yaSIoOXjtpNEoIftAipTUYoMhL
|
||||||
|
InXGlQBVA4shkekxp1N7HXe1Y/iMaPEyb3n+16pf3vdjKl7kaSkIhjdUz3oVUEYt
|
||||||
|
i8Z/XeJJ9H2aEGuiZh3kHixQcZczn8cg3dA9aeeyLSEnTkl/npzLf//669Ammyhs
|
||||||
|
XcAo58yvT0D4E0D/EEHf2N7HRX7j/TlyWvw/39SW0usiCrHPKDLxByLojxLdHzso
|
||||||
|
QIp/S04m+eWn6rmD+uUiRteN1hI5ncQiA3wo4G37mHnUEKo6TtTUh+sd/ku6a8HK
|
||||||
|
glMBcgqudDI90s1OpuIAWmuWpY//8xEG2YECAwEAAaNmMGQwDgYDVR0PAQH/BAQD
|
||||||
|
AgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFPqhoWZcrVY9mU7tuemR
|
||||||
|
RBnQIj1jMB8GA1UdIwQYMBaAFHNfYNi8ywOY9CsXNC42WqZg/7wfMA0GCSqGSIb3
|
||||||
|
DQEBCwUAA4IBAQB6zOLZ+YINEs72heHIWlPZ8c6WY8MDU+Be5w1M+BK2kpcVhCUK
|
||||||
|
PJO4nMXpgamEX8DIiaO7emsunwJzMSvavSPRnxXXTKIc0i/g1EbiDjnYX9d85DkC
|
||||||
|
E1LaAUCmCZBVi9fIe0H2r9whIh4uLWZA41oMnJx/MOmo3XyMfQoWcqaSFlMqfZM4
|
||||||
|
0rNoB/tdHLNuV4eIdaw2mlHxdWDtF4oH+HFm+2cVBUVC1jXKrFv/euRVtsTT+A6i
|
||||||
|
h2XBHKxQ1Y4HgAn0jACP2QSPEmuoQEIa57bEKEcZsBR8SDY6ZdTd2HLRIApcCOSF
|
||||||
|
MRM8CKLeF658I0XgF8D5EsYoKPsA+74Z+jDH
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID/zCCAuegAwIBAgIRAPVSMfFitmM5PhmbaOFoGfUwDQYJKoZIhvcNAQELBQAw
|
||||||
|
gZcxCzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ
|
||||||
|
bmMuMRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTEwMC4GA1UEAwwn
|
||||||
|
QW1hem9uIFJEUyB1cy1lYXN0LTEgUm9vdCBDQSBSU0EyMDQ4IEcxMRAwDgYDVQQH
|
||||||
|
DAdTZWF0dGxlMCAXDTIxMDUyNTIyMzQ1N1oYDzIwNjEwNTI1MjMzNDU3WjCBlzEL
|
||||||
|
MAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4x
|
||||||
|
EzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTAwLgYDVQQDDCdBbWF6
|
||||||
|
b24gUkRTIHVzLWVhc3QtMSBSb290IENBIFJTQTIwNDggRzExEDAOBgNVBAcMB1Nl
|
||||||
|
YXR0bGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDu9H7TBeGoDzMr
|
||||||
|
dxN6H8COntJX4IR6dbyhnj5qMD4xl/IWvp50lt0VpmMd+z2PNZzx8RazeGC5IniV
|
||||||
|
5nrLg0AKWRQ2A/lGGXbUrGXCSe09brMQCxWBSIYe1WZZ1iU1IJ/6Bp4D2YEHpXrW
|
||||||
|
bPkOq5x3YPcsoitgm1Xh8ygz6vb7PsvJvPbvRMnkDg5IqEThapPjmKb8ZJWyEFEE
|
||||||
|
QRrkCIRueB1EqQtJw0fvP4PKDlCJAKBEs/y049FoOqYpT3pRy0WKqPhWve+hScMd
|
||||||
|
6obq8kxTFy1IHACjHc51nrGII5Bt76/MpTWhnJIJrCnq1/Uc3Qs8IVeb+sLaFC8K
|
||||||
|
DI69Sw6bAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE7PCopt
|
||||||
|
lyOgtXX0Y1lObBUxuKaCMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOC
|
||||||
|
AQEAFj+bX8gLmMNefr5jRJfHjrL3iuZCjf7YEZgn89pS4z8408mjj9z6Q5D1H7yS
|
||||||
|
jNETVV8QaJip1qyhh5gRzRaArgGAYvi2/r0zPsy+Tgf7v1KGL5Lh8NT8iCEGGXwF
|
||||||
|
g3Ir+Nl3e+9XUp0eyyzBIjHtjLBm6yy8rGk9p6OtFDQnKF5OxwbAgip42CD75r/q
|
||||||
|
p421maEDDvvRFR4D+99JZxgAYDBGqRRceUoe16qDzbMvlz0A9paCZFclxeftAxv6
|
||||||
|
QlR5rItMz/XdzpBJUpYhdzM0gCzAzdQuVO5tjJxmXhkSMcDP+8Q+Uv6FA9k2VpUV
|
||||||
|
E/O5jgpqUJJ2Hc/5rs9VkAPXeA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
0Ws=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICrjCCAjSgAwIBAgIRAPAlEk8VJPmEzVRRaWvTh2AwCgYIKoZIzj0EAwMwgZYx
|
||||||
|
CzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJbmMu
|
||||||
|
MRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTEvMC0GA1UEAwwmQW1h
|
||||||
|
em9uIFJEUyB1cy1lYXN0LTEgUm9vdCBDQSBFQ0MzODQgRzExEDAOBgNVBAcMB1Nl
|
||||||
|
YXR0bGUwIBcNMjEwNTI1MjI0MTU1WhgPMjEyMTA1MjUyMzQxNTVaMIGWMQswCQYD
|
||||||
|
VQQGEwJVUzEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEG
|
||||||
|
A1UECwwKQW1hem9uIFJEUzELMAkGA1UECAwCV0ExLzAtBgNVBAMMJkFtYXpvbiBS
|
||||||
|
RFMgdXMtZWFzdC0xIFJvb3QgQ0EgRUNDMzg0IEcxMRAwDgYDVQQHDAdTZWF0dGxl
|
||||||
|
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEx5xjrup8II4HOJw15NTnS3H5yMrQGlbj
|
||||||
|
EDA5MMGnE9DmHp5dACIxmPXPMe/99nO7wNdl7G71OYPCgEvWm0FhdvVUeTb3LVnV
|
||||||
|
BnaXt32Ek7/oxGk1T+Df03C+W0vmuJ+wo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0G
|
||||||
|
A1UdDgQWBBTGXmqBWN/1tkSea4pNw0oHrjk2UDAOBgNVHQ8BAf8EBAMCAYYwCgYI
|
||||||
|
KoZIzj0EAwMDaAAwZQIxAIqqZWCSrIkZ7zsv/FygtAusW6yvlL935YAWYPVXU30m
|
||||||
|
jkMFLM+/RJ9GMvnO8jHfCgIwB+whlkcItzE9CRQ6CsMo/d5cEHDUu/QW6jSIh9BR
|
||||||
|
OGh9pTYPVkUbBiKPA7lVVhre
|
||||||
|
-----END CERTIFICATE-----
|
||||||
Loading…
Reference in new issue